地址

npm地址:https://www.npmjs.com/package/signature_pad

Signature_Pad 采用原生JS编写,基于 HTML 5 画布。用 Bézier 曲线进行插补,使线条更平滑。它适用于所有现代桌面和移动浏览器,不依赖于任何外部库。

演示

画布.gif

在 React-hooks 中使用

  1. import React, { useState, useEffect, useRef } from 'react';
  2. import SignaturePad from 'signature_pad';
  3. import { message, Button } from 'antd';
  4. import styles from './index.less';
  5. const Canvas = () => {
  6. const canvasRef = useRef(null);
  7. const spRef = useRef(null);
  8. const [imgUrl, setImgUrl] = useState('');
  9. // 初始化画板
  10. useEffect(() => {
  11. const canvas = canvasRef.current;
  12. const ratio = Math.max(window.devicePixelRatio || 1, 1);
  13. canvas.width = canvas.offsetWidth * ratio;
  14. canvas.height = canvas.offsetHeight * ratio;
  15. canvas.getContext('2d').scale(ratio, ratio);
  16. spRef.current = new SignaturePad(canvas, {
  17. penColor: '#FF0000',
  18. });
  19. }, []);
  20. // base 64 URL 转 Blob 对象
  21. const dataURLToBlob = (dataURL, type) => {
  22. // Code taken from https://github.com/ebidel/filer.js
  23. const parts = dataURL.split(';base64,');
  24. const contentType = parts[0].split(':')[1]; // 原始类型
  25. const raw = window.atob(parts[1]);
  26. const rawLength = raw.length;
  27. const uInt8Array = new Uint8Array(rawLength);
  28. for (let i = 0; i < rawLength; i++) {
  29. uInt8Array[i] = raw.charCodeAt(i);
  30. }
  31. return new Blob([uInt8Array], { type: type || contentType });
  32. };
  33. // base64 图片下载
  34. const download = (dataURL, filename) => {
  35. const blob = dataURLToBlob(dataURL);
  36. const url = window.URL.createObjectURL(blob);
  37. const a = document.createElement('a');
  38. a.style = 'display: none';
  39. a.href = url;
  40. a.download = filename;
  41. document.body.appendChild(a);
  42. a.click();
  43. window.URL.revokeObjectURL(url);
  44. };
  45. // 显示图片
  46. const onShow = () => {
  47. const isEmpty = spRef.current.isEmpty();
  48. if (isEmpty) {
  49. message.info('当前画布为空');
  50. } else {
  51. const spUrl = spRef.current.toDataURL();
  52. setImgUrl(spUrl);
  53. // const file = dataURLToBlob(spUrl, 'image/png');
  54. // console.log(spUrl, file, 'spUrl');
  55. }
  56. };
  57. // 下载
  58. const onDownload = () => {
  59. const isEmpty = spRef.current.isEmpty();
  60. if (isEmpty) {
  61. message.info('当前画布为空');
  62. } else {
  63. const spUrl = spRef.current.toDataURL();
  64. download(spUrl, '画布图片');
  65. }
  66. };
  67. // 清空画布
  68. const clearSp = () => {
  69. spRef.current.clear && spRef.current.clear();
  70. };
  71. return (
  72. <div className={styles.canvas}>
  73. <h4>
  74. 画布/签名板
  75. <Button onClick={onShow}>显示图片</Button>
  76. <Button onClick={onDownload}>下载图片</Button>
  77. <Button onClick={clearSp}>清空</Button>
  78. </h4>
  79. <div className={styles.content}>
  80. <canvas ref={canvasRef} style={{ border: '1px solid #000' }} />
  81. {imgUrl && <img src={imgUrl} alt="加载失败" />}
  82. </div>
  83. </div>
  84. );
  85. };
  86. export default Canvas;

参考资料

base64 图片下载 - base 64 转 Blob 对象