标题vue2 canvas实现签名
<template>
<div>
<div class="canvasBox" ref="canvasHW" style="border: 1px solid #ccc">
<canvas
ref="canvasF"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
@mousedown="mouseDown"
@mousemove="mouseMove"
@mouseup="mouseUp"
></canvas>
<el-button type="primary" @click="downloadImg">下载签名</el-button>
<el-button type="primary" @click="overwrite">重写</el-button>
<el-button type="primary" @click="commit">提交签名</el-button>
</div>
<img class="imgCanvas" :src="imgUrl" />
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
stageInfo: "",
imgUrl: "",
client: {},
points: [],
canvasTxt: null,
startX: 0,
startY: 0,
moveY: 0,
moveX: 0,
endY: 0,
endX: 0,
w: null,
h: null,
isDown: false,
isViewAutograph: this.$route.query.isViews > 0,
contractSuccess: this.$route.query.contractSuccess,
};
},
mounted() {
let canvas = this.$refs.canvasF;
canvas.height = this.$refs.canvasHW.offsetHeight - 500;
canvas.width = this.$refs.canvasHW.offsetWidth - 50;
this.canvasTxt = canvas.getContext("2d");
this.stageInfo = canvas.getBoundingClientRect();
},
methods: {
//mobile
touchStart(ev) {
ev = ev || event;
ev.preventDefault();
if (ev.touches.length == 1) {
let obj = {
x: ev.targetTouches[0].clienX,
y: ev.targetTouches[0].clientY,
};
this.startX = obj.x;
this.startY = obj.y;
this.canvasTxt.beginPath();
this.canvasTxt.moveTo(this.startX, this.startY);
this.canvasTxt.lineTo(obj.x, obj.y);
this.canvasTxt.stroke();
this.canvasTxt.closePath();
this.points.push(obj);
}
},
touchMove(ev) {
ev = ev || event;
ev.preventDefault();
if (ev.touches.length == 1) {
let obj = {
x: ev.targetTouches[0].clientX - this.stageInfo.left,
y: ev.targetTouches[0].clientY - this.stageInfo.top,
};
this.moveY = obj.y;
this.moveX = obj.x;
this.canvasTxt.beginPath();
this.canvasTxt.moveTo(this.startX, this.startY);
this.canvasTxt.lineTo(obj.x, obj.y);
this.canvasTxt.stroke();
this.canvasTxt.closePath();
this.startY = obj.y;
this.startX = obj.x;
this.points.push(obj);
}
},
touchEnd(ev) {
ev = ev || event;
ev.preventDefault();
if (ev.touches.length == 1) {
let obj = {
x: ev.targetTouches[0].clientX - this.stageInfo.left,
y: ev.targetTouches[0].clientY - this.stageInfo.top,
};
this.canvasTxt.beginPath();
this.canvasTxt.moveTo(this.startX, this.startY);
this.canvasTxt.lineTo(obj.x, obj.y);
this.canvasTxt.stroke();
this.canvasTxt.closePath();
this.points.push(obj);
}
},
//pc
mouseDown(ev) {
ev = ev || event;
ev.preventDefault();
if (1) {
let obj = {
x: ev.offsetX,
y: ev.offsetY,
};
this.startX = obj.x;
this.startY = obj.y;
this.canvasTxt.beginPath();
this.canvasTxt.moveTo(this.startX, this.startY);
this.canvasTxt.lineTo(obj.x, obj.y);
this.canvasTxt.stroke();
this.canvasTxt.closePath();
this.points.push(obj);
this.isDown = true;
}
},
mouseMove(ev) {
ev = ev || event;
ev.preventDefault();
if (this.isDown) {
let obj = {
x: ev.offsetX,
y: ev.offsetY,
};
this.moveY = obj.y;
this.moveX = obj.x;
this.canvasTxt.beginPath();
this.canvasTxt.moveTo(this.startX, this.startY);
this.canvasTxt.lineTo(obj.x, obj.y);
this.canvasTxt.stroke();
this.canvasTxt.closePath();
this.startY = obj.y;
this.startX = obj.x;
this.points.push(obj);
}
},
mouseUp(ev) {
ev = ev || event;
ev.preventDefault();
if (1) {
let obj = {
x: ev.offsetX,
y: ev.offsetY,
};
this.canvasTxt.beginPath();
this.canvasTxt.moveTo(this.startX, this.startY);
this.canvasTxt.lineTo(obj.x, obj.y);
this.canvasTxt.stroke();
this.canvasTxt.closePath();
this.points.push(obj);
this.points.push({ x: -1, y: -1 });
this.isDown = false;
}
},
//重写
overwrite() {
this.canvasTxt.clearRect(
0,
0,
this.$refs.canvasF.width,
this.$refs.canvasF.height
);
this.points = [];
},
isCanvasBlank(canvas) {
const blank = document.createElement("canvas"); //系统获取一个空canvas对象
blank.width = canvas.width;
blank.height = canvas.height;
return canvas.toDataURL() == blank.toDataURL(); //比较值相等则为空
},
downloadImg() {
if (this.isCanvasBlank(this.$refs.canvasF)) {
this.$message.warning("请输入签名");
return;
}
const el = document.createElement("a");
// 设置 href 为图片经过 base64 编码后的字符串,默认为 png 格式
el.href = this.$refs.canvasF.toDataURL();
el.download = "签名";
// 创建一个点击事件并对 a 标签进行触发
const event = new MouseEvent("click");
el.dispatchEvent(event);
},
//提交签名
commit() {
this.imgUrl = this.$refs.canvasF.toDataURL();
console.log(this.$refs.canvasF.toDataURL()); //签名img回传后台
const file = this.dataURLtoFile(this.imgUrl, "签名.png");
if (!file) return;
const formData = new FormData();
formData.append("file", file);
axios({
url: "/api/v1/files",
method: "post",
data: formData,
headers: {
"Content-Type": "multipart/form-data",
},
});
},
// 转为file格式,可传递给后端
dataURLtoFile(dataurl, filename) {
const arr = dataurl.split(",");
if (!arr.length) return;
const mime = arr[0].match(/:(.*?);/);
if (mime) {
const bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, { type: mime[1] });
}
},
},
};
</script>