地址
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.js
const 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;