手写签名
Ydesign 画布本身不支持用户在其上手绘(这也符合"布局工具"的定位)。但你可以用一个 独立的手写板组件 采集签名,再把结果作为 Image 元素放到画布上。
用 react-signature-canvas 做手写板
react-signature-canvas 是一个轻量的 React 签名板。
npm install react-signature-canvas
自定义侧边面板
import { useRef } from 'react';
import SignatureCanvas from 'react-signature-canvas';
import { Button } from 'antd';
import { observer } from 'mobx-react-lite';
import { Pen } from 'lucide-react';
import {
SectionTab,
DEFAULT_SECTIONS,
SidePanel,
} from '@ydesign/react-editor/side-panel';
import type { Section } from '@ydesign/react-editor/side-panel';
const SignatureSection: Section = {
name: 'signature',
Tab: observer(props => (
<SectionTab name="手写签名" {...props}>
<Pen size={20} />
</SectionTab>
)),
Panel: observer(({ store }) => {
const padRef = useRef<SignatureCanvas>(null);
const handleClear = () => padRef.current?.clear();
const handleAddToCanvas = () => {
const pad = padRef.current;
if (!pad || pad.isEmpty()) return;
// 导出手写签名为透明背景 PNG dataURL
const dataUrl = pad.getTrimmedCanvas().toDataURL('image/png');
store.addElement({
type: 'Image',
src: dataUrl,
left: store.width / 2 - 150,
top: store.height / 2 - 40,
width: 300,
height: 80,
});
pad.clear();
};
return (
<div style={{ padding: 12 }}>
<p style={{ marginBottom: 8 }}>在下方签名框里手写:</p>
<div style={{ border: '1px solid #d9d9d9', borderRadius: 4, marginBottom: 12 }}>
<SignatureCanvas
ref={padRef}
penColor="black"
canvasProps={{ width: 320, height: 160 }}
/>
</div>
<div style={{ display: 'flex', gap: 8 }}>
<Button onClick={handleClear} block>
清空
</Button>
<Button type="primary" onClick={handleAddToCanvas} block>
加到画布
</Button>
</div>
</div>
);
}),
};
// 注册
<SidePanel store={store} sections={[...DEFAULT_SECTIONS, SignatureSection]} />;
更高级的方案
① 签名导出为 SVG(无损缩放)
react-signature-canvas 仅支持 PNG 输出。如果需要 SVG(可任意缩放不模糊),换成 signature_pad:
import SignaturePad from 'signature_pad';
const pad = new SignaturePad(canvasEl);
// ...用户手写...
const svg = pad.toSVG(); // 👈 SVG 字符串
import { svgToURL } from '@ydesign/react-editor/utils/svg';
store.addElement({
type: 'Image',
src: svgToURL(svg),
// ...
});
② 支持合同场景:把签名"压平到 PDF"
业务场景里的签名通常要和文档一起导出为 PDF。思路:
- 画布按 A4 尺寸(2480 × 3508 @ 300dpi)排好合同内容
- 用户签名后加到画布
- 调
store.saveAsImage({ multiplier: 1, format: 'png' })得到整页 PNG - 再用 jsPDF 把 PNG 包成 PDF
③ 服务端存储签名数据
签名 dataURL 通常很大(几十 KB)。生产环境建议:
- 签名生成后上传到后端 / OSS
- 用返回的短 URL 替换
src - 避免把大段 base64 留在
store.toJSON()里
相关文档
- 👉 自定义 Section —— 侧边面板扩展
- 👉 上传面板 —— 大图 / 签名上传到自己的存储
- 👉 单位与度量 —— A4 合同尺寸换算