js原生实现手写签名与使用signature_pad库实现手写签名
原生写法
完整代码
使用 canvas 画布绘制,input color实现颜色选择
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>手写签名</title><style>#signature-pad {border: 1px solid #000;width: 900px;height: 500px;}</style></head><body><canvas id="signature-pad"></canvas><input type="color" id="color-picker" value="#000000" /><button onclick="clearCanvas()">清除</button><button onclick="saveSignature()">保存</button></body><script>const canvas = document.getElementById('signature-pad')const ctx = canvas.getContext('2d')let painting = falseconst colorPicker = document.getElementById('color-picker')/*** 调整画布尺寸以适配高分辨率屏幕* 根据设备像素比设置画布的实际宽高,并进行缩放,防止模糊*/function resizeCanvas() {const ratio = Math.max(window.devicePixelRatio || 1, 1)canvas.width = canvas.offsetWidth * ratiocanvas.height = canvas.offsetHeight * ratiocanvas.getContext('2d').scale(ratio, ratio)}resizeCanvas()window.addEventListener('resize', resizeCanvas)/*** 开始绘制的事件处理函数* 当鼠标按下时触发,设置绘画状态为true并开始绘制* @param {MouseEvent} e - 鼠标事件对象*/function startPosition(e) {painting = truedrawLine(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop)}/*** 结束绘制的事件处理函数* 当鼠标松开或离开画布时触发,重置绘画状态和路径*/function finishPosition() {painting = falsectx.beginPath()}/*** 绘制线条函数* 在画布上绘制从上一个点到当前点的线段* @param {number} x - 当前点的x坐标(相对于画布)* @param {number} y - 当前点的y坐标(相对于画布)*/function drawLine(x, y) {if (!painting) returnctx.lineWidth = 3 // 线条宽度ctx.lineCap = 'round' // 让线条两头圆润// ctx.strokeStyle = 'red' // 设置线条颜色ctx.strokeStyle = colorPicker.value // 使用颜色选择器的值ctx.lineTo(x, y)ctx.stroke()ctx.beginPath() // 重置路径,继续绘制新的线条ctx.moveTo(x, y) // 设置下一个点的起始位置为当前点}// 绑定鼠标事件监听器canvas.addEventListener('mousedown', startPosition)canvas.addEventListener('mouseup', finishPosition)canvas.addEventListener('mousemove', function (e) {if (painting) {drawLine(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop)}})canvas.addEventListener('mouseout', finishPosition) // 当鼠标离开画布时停止绘画/*** 清除画布内容* 使用clearRect方法清空整个画布区域*/function clearCanvas() {ctx.clearRect(0, 0, canvas.width, canvas.height) // 清除画布内容}/*** 保存签名图片* 将画布内容导出为PNG格式的图片并下载到本地*/function saveSignature() {const image = canvas.toDataURL('image/png') // 将画布内容转换为DataURL格式的PNG图片数据console.log(image)const link = document.createElement('a')link.download = 'download.png'link.href = imagedocument.body.appendChild(link)link.click()document.body.removeChild(link)}</script>
</html>
使用signature_pad库
完整代码
index.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>手写签名</title><meta name="viewport" content="width=device-width, initial-scale=1.0" /><script src="https://cdn.jsdelivr.net/npm/signature_pad@4.1.7/dist/signature_pad.umd.min.js"></script><style>#signature-pad {border: 1px solid #000;width: 1200px;height: 500px;}</style></head><body><canvas id="signature-pad"></canvas><button onclick="clearCanvas()">清除</button><button onclick="saveSignature()">保存</button><script>const canvas = document.querySelector('canvas')const signaturePad = new SignaturePad(canvas, {minWidth: 3,maxWidth: 3,penColor: 'rgb(66, 133, 244)'})function resizeCanvas() {const ratio = Math.max(window.devicePixelRatio || 1, 1)canvas.width = canvas.offsetWidth * ratiocanvas.height = canvas.offsetHeight * ratiocanvas.getContext('2d').scale(ratio, ratio)signaturePad.clear()}resizeCanvas()window.addEventListener('resize', resizeCanvas)function clearCanvas() {signaturePad.clear()}async function saveSignature() {const png_data = await signaturePad.toDataURL()// console.log(png_data)const link = document.createElement('a')link.download = 'download.png'link.href = png_datadocument.body.appendChild(link)link.click()document.body.removeChild(link)// console.log(signaturePad.toDataURL('image/jpeg'))}</script></body>
</html>
代码解释
1、初始化
1、获取canvas画布dom;
2、初始化 SignaturePad 库;
3、设置初始属性;
const canvas = document.querySelector('canvas')
const signaturePad = new SignaturePad(canvas, {minWidth: 3,maxWidth: 3,penColor: 'rgb(66, 133, 244)'
})
2、处理高DPI屏幕
如果不动态设置画布比例,会出现画笔错位问题
function resizeCanvas() {const ratio = Math.max(window.devicePixelRatio || 1, 1)canvas.width = canvas.offsetWidth * ratiocanvas.height = canvas.offsetHeight * ratiocanvas.getContext('2d').scale(ratio, ratio)signaturePad.clear()
}
resizeCanvas()
window.addEventListener('resize', resizeCanvas)
3、清除按钮
调用库自带方法清除已写内容
function clearCanvas() {signaturePad.clear()
}
4、保存按钮
生成png图片并下载
async function saveSignature() {const png_data = await signaturePad.toDataURL()// console.log(png_data)const link = document.createElement('a')link.download = 'download.png'link.href = png_datadocument.body.appendChild(link)link.click()document.body.removeChild(link)
}
官方参考
signature_pad - npm