话不多说上代码
页面代码
<template>
<div class="signHandle">
<canvas ref="signHandle" class="canvas" />
<div class="btn_container" :style="{ height: height + 'px' }">
<van-button style="margin-left: auto;" round @touchstart="clearHandle"
>重新签名</van-button
>
<van-button style="margin:0 10px;" type="info" round @touchstart="saveImg"
>提交签名</van-button
>
</div>
</div>
</template>
<script>
// 解构设备的宽度, 和 高度
const { clientWidth, clientHeight } = document.documentElement;
export default {
data() {
return {
height: 550,
direction: false, // true 代表横屏, false 代表'竖屏'
el: "", // canvas dom
ctx: "", // canvas context
background: "#fff", // canvas background-color
color: "#000", // 绘制时线条的颜色
linewidth: 3, // 线条的宽度
};
},
created() {
window.addEventListener(
"onorientationchange" in window ? "orientationchange" : "resize",
() => {
if (window.orientation === 180 || window.orientation === 0) {
this.direction = false;
this.draw();
}
if (window.orientation === 90 || window.orientation === -90) {
this.direction = true;
this.draw();
}
},
false
);
},
mounted() {
this.draw();
},
methods: {
radioHandle(value) {
this.color = value;
this.setCanvas();
},
handler(e){
e.preventDefault();
},
// 添加绘制 line
draw() {
document.addEventListener("touchmove", this.handler, {
passive: false,
});
this.el = this.$refs.signHandle;
this.initCanvas();
},
// 初始化canvas配置
initCanvas() {
const { height, direction, el } = this;
if (direction) {
el.width = clientHeight;
el.height = clientWidth - height;
} else {
el.width = clientWidth;
el.height = clientHeight - height;
}
this.ctx = el.getContext("2d");
this.setCanvas();
this.drawStart();
this.drawing();
this.drawEnd();
},
// 配置 canvas
setCanvas() {
const { ctx, height, direction } = this;
console.log(direction);
// 设置背景色
ctx.fillStyle = this.background;
// 绘制矩形
if (direction) {
ctx.fillRect(0, 0, clientHeight, clientWidth - height);
} else {
ctx.fillRect(0, 0, clientWidth, clientHeight - height);
}
// 设置线条颜色
ctx.strokeStyle = this.color;
// 设置线宽
ctx.lineWidth = this.linewidth;
// 设置线条两头的结束点和开始点是圆形的
ctx.lineCap = "round";
},
// 开始绘制
drawStart() {
const { el, ctx } = this;
el.addEventListener(
"touchstart",
(e) => {
ctx.beginPath();
ctx.moveTo(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
},
false
);
},
// 绘制中
drawing() {
const { el, ctx } = this;
el.addEventListener(
"touchmove",
(e) => {
ctx.lineTo(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
ctx.stroke();
},
false
);
},
// 绘制结束
drawEnd() {
const { el, ctx } = this;
el.addEventListener("touchend", () => ctx.closePath(), false);
},
// 清空
clearHandle() {
this.initCanvas();
},
// 保存信息
saveImg() {
const { el, ctx } = this;
const imgBase64 = el.toDataURL("image/jpeg");
var arr = imgBase64.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
var file = new File([u8arr], "签名", { type: mime });
this.handerImg(file,clientWidth / 5, el.height / 5)
},
//画图
handerImg(file,width,height){
let that = this
var reader = new FileReader();
var img = document.createElement('img');
reader.onload = function (e) {
img.src = e.target.result;
img.onload = function () {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = width;//canvas的宽=图片的宽
canvas.height = height;//canvas的高=图片的高
context.clearRect(0, 0, width, height)//清理canvas
context.drawImage(img, 0, 0, width, height)//canvas绘图
var imgBase64 = canvas.toDataURL("image/jpeg");//canvas导出成为base64
var arr = imgBase64.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
var file = new File([u8arr], "签名", { type: mime });
console.log(file);
console.log(imgBase64);
}
}
reader.readAsDataURL(file);
},
defaultOn() {
document.removeEventListener("touchmove", this.handler, {
passive: false,
});
},
},
beforeDestroy() {
this.defaultOn();
console.log(11111);
},
};
</script>
<style lang="less" scoped>
.signHandle {
position: relative;
width: 100%;
height: 100%;
.canvas {
box-sizing: border-box;
}
.btn_container {
padding-top: 10px;
border-top: 1px solid #ccc;
background-color: #fff;
display: flex;
box-sizing: border-box;
}
}
</style>
file对象是最后生成的图片对象,根据需求传给后端进行合成