地址
npm地址:https://www.npmjs.com/package/signature_pad
Signature_Pad 采用原生JS编写,基于 HTML 5 画布。用 Bézier 曲线进行插补,使线条更平滑。它适用于所有现代桌面和移动浏览器,不依赖于任何外部库。
演示

在 React-hooks 中使用
import React, { useState, useEffect, useRef } from 'react';import SignaturePad from 'signature_pad';import { message, Button } from 'antd';import styles from './index.less';const Canvas = () => {const canvasRef = useRef(null);const spRef = useRef(null);const [imgUrl, setImgUrl] = useState('');// 初始化画板useEffect(() => {const canvas = canvasRef.current;const ratio = Math.max(window.devicePixelRatio || 1, 1);canvas.width = canvas.offsetWidth * ratio;canvas.height = canvas.offsetHeight * ratio;canvas.getContext('2d').scale(ratio, ratio);spRef.current = new SignaturePad(canvas, {penColor: '#FF0000',});}, []);// base 64 URL 转 Blob 对象const dataURLToBlob = (dataURL, type) => {// Code taken from https://github.com/ebidel/filer.jsconst parts = dataURL.split(';base64,');const contentType = parts[0].split(':')[1]; // 原始类型const raw = window.atob(parts[1]);const rawLength = raw.length;const uInt8Array = new Uint8Array(rawLength);for (let i = 0; i < rawLength; i++) {uInt8Array[i] = raw.charCodeAt(i);}return new Blob([uInt8Array], { type: type || contentType });};// base64 图片下载const download = (dataURL, filename) => {const blob = dataURLToBlob(dataURL);const url = window.URL.createObjectURL(blob);const a = document.createElement('a');a.style = 'display: none';a.href = url;a.download = filename;document.body.appendChild(a);a.click();window.URL.revokeObjectURL(url);};// 显示图片const onShow = () => {const isEmpty = spRef.current.isEmpty();if (isEmpty) {message.info('当前画布为空');} else {const spUrl = spRef.current.toDataURL();setImgUrl(spUrl);// const file = dataURLToBlob(spUrl, 'image/png');// console.log(spUrl, file, 'spUrl');}};// 下载const onDownload = () => {const isEmpty = spRef.current.isEmpty();if (isEmpty) {message.info('当前画布为空');} else {const spUrl = spRef.current.toDataURL();download(spUrl, '画布图片');}};// 清空画布const clearSp = () => {spRef.current.clear && spRef.current.clear();};return (<div className={styles.canvas}><h4>画布/签名板<Button onClick={onShow}>显示图片</Button><Button onClick={onDownload}>下载图片</Button><Button onClick={clearSp}>清空</Button></h4><div className={styles.content}><canvas ref={canvasRef} style={{ border: '1px solid #000' }} />{imgUrl && <img src={imgUrl} alt="加载失败" />}</div></div>);};export default Canvas;
