2025-10-27 10:37:12

如何通过canvas实现电子签名

想要实现一个电子签名,可以支持鼠标签名,还能类似书法效果线条有粗有细,同时可以导出成图片.

一、实现连贯的划线

1)首先需要注册鼠标下压、鼠标放开、鼠标移出和鼠标移动事件,通过鼠标下压赋值downFlag标记开始绘制

2) 鼠标移动时,将当前坐标位置传入绘制方法,通过lineTo方法实现绘制

/**

* 按下鼠标启动绘制标记

**/

canvas.addEventListener('mousedown', e => {

preCoord = [e.offsetX, e.offsetY, new Date().getTime()];

downFlag = true;

})

/**

* 鼠标松开结束绘制

**/

canvas.addEventListener('mouseup', e => {

downFlag = false;

})

canvas.addEventListener('mouseout', () => {

downFlag = false;

})

/**

* 鼠标移动时绘制文字

**/

canvas.addEventListener('mousemove', e => {

if (downFlag) {

const coord = [e.offsetX, e.offsetY];

drawSign(coord);

preCoord = [...coord, new Date().getTime()];

}

})

3) 启动线的绘制,其中注释的线段

function drawSign(coord) {

// 为了实现阶段性线的不同粗细程度,所以每次绘制必须重新开始一段路径

ctx.beginPath();

getColor(coord);

ctx.lineTo(...preCoord);

ctx.lineTo(...coord);

ctx.stroke();

ctx.closePath();

}

二、为了美观,实现书法类似的效果,需要设每个线段设置不同的宽度才可以

1)根据每两个事件点的时间差计算一个倍数关系,然后乘以一个基础宽度就可以得到不同的宽度,本文实现的效果是绘制越慢线条越宽,越快线条越窄

2) 设置线的连接方式和线端点效果,使整个线条看起来更加圆滑

/**

* 根据绘制时间差设置绘制线宽

**/

function getColor(coord) {

if (preCoord.length === 0) {

return;

}

// 当前是计算的每两个点的时间差是五毫秒的倍数

const tempMulti = (new Date().getTime() - preCoord[2]) / 5;

if (tempMulti > multi) {

multi = multi * 1.4;

} else {

multi = multi * 0.9;

}

if (multi > 5) {

multi = 5;

}

if (multi < 1) {

multi = 1;

}

ctx.lineWidth = 2 * multi;

// 通过设置连线效果和线端点效果可以使线条看起来更圆滑

ctx.lineCap = 'round';

ctx.lineJoin = 'round';

ctx.strokeStyle = 'rgba(153, 153, 153, 1)';

}

三、下面奉上完整的代码和效果图

signature

完整代码

煎荷包蛋时,有人加盐,有人加面粉,大厨:都不对!教你正确做法
天天炫斗停更了吗?天天炫斗停止运作