小编最近的项目与合同有关,与合同有关就避免不了合同的签署,自然而然就需要搞个签名版啦,废话少说,上代码比较实在。
sign.vue
<template>
<div class="signHandle">
<canvas
ref="signHandle"
class="canvas"
id="canvas"
@touchstart="drawStart"
@touchmove="drawing"
@touchend="draeEnd"
>
</canvas>
<div class="btn-box">
<span class="clear-btn" @click.stop="clearSign">重置</span>
<span class="submit-btn" @click.stop="saveSign">提交</span>
</div>
</div>
</template>
<script>
const { clientWidth, clientHeight } = document.documentElement;
export default {
props: {
//canvas 宽度
canvasWidth: {
type: Number,
default: clientWidth,
},
//canvas 高度
canvasHeight: {
type: Number,
default: clientHeight,
},
//canvas 背景色
canvasBackground: {
type: String,
default: "#fff",
},
//线条颜色
lineColor: {
type: String,
default: "#000",
},
//线条宽度
lineWidth: {
type: Number,
default: 3,
},
//线条两端形状
lineRound: {
type: String,
default: "round", //圆形
},
},
data() {
return {
direction: false, //屏幕方向 true:横屏 false:竖屏
el: "", //canvas dom
ctx: "", //canvas内容
};
},
created() {
this.initPhoneDirection();
},
mounted() {
this.draw();
},
methods: {
/**
* 判断当前手机为竖屏还是横屏
*/
initPhoneDirection() {
window.addEventListener(
"onorientationchange" in window ? "oorientationchange" : "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
);
},
/**
* 添加绘制线
*/
draw() {
document.addEventListener("touchmove", (e) => e.preventDefault(), {
passive: false,
});
this.el = this.$refs.signHandle;
this.initCanvas();
},
/**
* 初始化canvas配置
*/
initCanvas() {
this.el.width = this.canvasWidth;
this.el.height = this.canvasHeight;
this.ctx = this.el.getContext("2d");
this.setCanvas();
},
/**
* canvas配置
*/
setCanvas() {
this.ctx.fillStyle = this.canvasBackground;
//绘制矩形
if (this.direction) {
this.ctx.fillRect(0, 0, this.canvasHeight, this.canvasWidth);
} else {
this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
}
//设置线条颜色
this.ctx.strokeStyle = this.lineColor;
//设置线条宽度
this.ctx.lineWidth = this.lineWidth;
//设置线条两端形状
this.ctx.lineCap = this.lineRound;
},
/**
* 开始绘制
*/
drawStart(e) {
this.ctx.beginPath();
this.ctx.moveTo(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
},
/**
* 绘制过程
*/
drawing(e) {
this.ctx.lineTo(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
this.ctx.stroke();
},
/**
* 绘制结束
*/
drawEnd(e) {
this.ctx.closePath();
},
/**
* 重置
*/
clearSign() {
this.initCanvas();
},
/**
* 提交
*/
saveSign() {
const imagesBase64 = this.el.toDataURL();
console.log("imagesBase64", imagesBase64);
},
},
};
</script>
<style lang="scss" scoped>
.signHandle {
width: 100%;
canvas {
display: blick;
}
.btn-box {
width: 100%;
display: flex;
justify-content: space-between;
span {
display: block;
width: 50%;
height: 44px;
text-align: center;
line-height: 44px;
color: #333;
background: #fff;
}
.submit-btn {
color: #fff;
background: #fa5050;
}
}
}
</style>
在开发过程中,小编发现了一个问题,不知道有没有童鞋遇到,问题:只要canvas或canvas的父级或canvas的父级的父级,总而言之,只要canvas设置了定位,无论是什么定位,只要存在偏移,绘制就会出错,也不能说出错,是下笔的地方与实际绘制出的地方就会偏移设置定位偏移的量,听起来有些拗口,假设,小编原本在(10,10)坐标下笔开始绘制的,但是捏,小编设置定位距离顶部10px,那么绘制的时候,它可能就是从(10,20)坐标开始绘制的。小编猜测,是设置定位之后,x轴和y轴改变了,导致坐标都改变了导致的。小编想了个较笨的解决方案,就是,如果距离左右有偏移,在moveTo和lineTo的x轴坐标就需要进行相应的加减,如果是距离上下有偏移,则y轴坐标就需要进行相应的加减,至于加减多少就需要自己调试了;如果有偏移,该组件就无法进行通用了,但如果没有偏移,这个组件是通用的哦~希望对各位同学有帮助。