React 实现 H5 签名签字(signature)
基本功能
签字,切换颜色 ,可清空,可提交图片。
接入参考
1.依赖安装,这里用到了开源库《signature_pad》文档地址
npm i signature_pad
2.引入对应的npm包
import SignaturePad from 'signature_pad';
3.挂载相应的canvas dom和SignaturePad实例这里前端用到的技术栈是 react,函数式组件
<canvas ref={canvasRef}>
暂不支持手绘功能。
</canvas>
import React, { useRef, useEffect, useState } from 'react';
const canvasRef = useRef<HTMLCanvasElement>(null); // canvas dom
const signaturePadRef = useRef<SignaturePad>(); // signature_pad实例
const [penColor, setPenColor] = useState(blackPenColor);
useEffect(() => {
const canvas = canvasRef.current;
if (canvas) {
canvas.width = canvas.getBoundingClientRect().width; // 让画布自适应
canvas.height = canvas.getBoundingClientRect().height;
signaturePadRef.current = new SignaturePad(canvas, {
// backgroundColor: '#fff', // 签字区域背景色 Defaults to "rgba(0,0,0,0)"
minWidth: 1, // 签字线最小宽度 Defaults to 0.5
maxWidth: 4, // 签字线最大宽度 Defaults to 2.5
penColor, // 签字线颜色 Defaults to "black"
});
}
}, []);
4.到这里签字区域应该展示出来了。额外的需求去参考文档api即可
签字图片提交的提交方式
1.base64
signaturePadRef?.current?.toDataURL() // 返回签字图片的base64地址
不过因为base64比较大,直接保存比较占内存,这里会用到一些优化处理。把base64做文件上传然后后端返回cdn链接即可。
const convertBase64UrlToBlob = (urlData: any, callback: any) => {
// 将base64转化为文件格式
const arr = urlData.split(',');
const mime = arr[0].match(/:(.*?);/)[1];
const bstr = atob(arr[1]); // atob方法用于解码base64
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Promise((resolve) => {
resolve(
callback(
new Blob([u8arr], {
type: mime,
}),
),
);
});
};
convertBase64UrlToBlob(res, (res1) => {
const compresFile = new File([res1], 'sign.png', {
type: 'image/png',
});
const formData = new FormData();
formData.append('file', compresFile);
// 这里调用上传文件服务,上传binary
uploadFile(formData).then((res2: any) => {
if (res2?.datasuccess) {
// 成功后续逻辑。。
}
}).catch(
(err2) => {
// 异常捕获下
}
);
});
保存图片支持格式:
signaturePad.toDataURL(); // save image as PNG
signaturePad.toDataURL("image/jpeg"); // save image as JPEG
signaturePad.toDataURL("image/jpeg", 0.5); // save image as JPEG with 0.5 image quality
signaturePad.toDataURL("image/svg+xml"); // save image as SVG
2.canvas坐标数组
// Returns signature image as an array of point groups
const data = signaturePad.toData();
回显,base64,坐标数组都能回显
// Draws signature image from an array of point groups
signaturePad.fromData(data);
// Draws signature image from an array of point groups, without clearing your existing image (clear defaults to true if not provided)
signaturePad.fromData(data, { clear: false });
其他问题,可参考官方文档issues,比如画布自适应问题
function resizeCanvas() {
const ratio = Math.max(window.devicePixelRatio || 1, 1);
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
canvas.getContext("2d").scale(ratio, ratio);
signaturePad.clear(); // otherwise isEmpty() might return incorrect value
}
window.addEventListener("resize", resizeCanvas);
resizeCanvas();
效果图