UNPKG

vue2-signature

Version:

Vue 2 signature pad component

442 lines (371 loc) 13.6 kB
<div align="center"> <h1>✍️ Vue2 Signature</h1> <p>一个流畅优雅的 Vue 2 电子签名组件</p> <p><strong>基于 <a href="https://github.com/szimek/signature_pad">signature_pad</a></strong> - 最流行的 HTML5 Canvas 签名库</p> <p> <a href="https://www.npmjs.com/package/vue2-signature"> <img src="https://img.shields.io/npm/v/vue2-signature.svg?style=flat-square" alt="npm version"> </a> <a href="./LICENSE"> <img src="https://img.shields.io/npm/l/vue2-signature.svg?style=flat-square" alt="license"> </a> </p> </div> --- ## 特性 - 📱 **全平台支持** - 完美支持 PC 端鼠标和移动端触摸操作 - 🎨 **高度可定制** - 支持自定义笔触颜色宽度背景色画布尺寸等 - 💾 **丰富的导出功能** - 支持导出 Base64BlobFile 对象,支持 PNGJPEGSVG 格式 - ✂️ **自动裁剪** - 支持自动裁剪签名周围的空白区域 - 🔄 **历史记录管理** - 内置撤销(Undo)和重做(Redo)功能 - 🖼️ **水印功能** - 支持添加自定义文本水印,可配置样式和位置 - 🚫 **状态控制** - 支持禁用(只读)和启用编辑模式 - 📐 **响应式设计** - 支持百分比宽高,自动适应容器大小 ## 🚀 快速开始 ### 安装 ```bash # 使用 npm npm install vue2-signature # 使用 yarn yarn add vue2-signature ``` ### 全局注册 ```javascript // main.js import Vue from 'vue'; import Vue2Signature from "vue2-signature"; Vue.use(Vue2Signature); ``` ### 局部注册 ```javascript import Vue2Signature from "vue2-signature"; export default { components: { Vue2Signature } // ... }; ``` ### 基本使用示例 ```vue <template> <div class="signature-container"> <Vue2Signature ref="signature" :sigOption="options" w="100%" h="400px" :disabled="disabled" :defaultUrl="defaultUrl" @ready="onReady" @begin="onBegin" @end="onEnd" /> <div class="actions"> <button @click="save('base64')">保存为 Base64</button> <button @click="save('file')">保存为 File</button> <button @click="clear">清空</button> <button @click="undo">撤销</button> <button @click="redo">重做</button> <button @click="addWaterMark">添加水印</button> <button @click="trim">获取裁剪后数据</button> <button @click="toggleDisabled">禁用/启用</button> </div> </div> </template> <script> export default { data() { return { // signature_pad 的选项 options: { penColor: "rgb(0, 0, 0)", backgroundColor: "rgb(245, 245, 245)", // 稍带灰色的背景 }, disabled: false, defaultUrl: "", // 初始显示的签名图片地址 }; }, methods: { onReady(signaturePad) { console.log("Signature pad ready", signaturePad); }, onBegin() { console.log("Stroke begin"); }, onEnd() { console.log("Stroke end"); }, save(type) { // save 方法第二个参数可以配置 type, format, quality 等 const result = this.$refs.signature.save("image/png", { type: type, // 'base64' | 'blob' | 'file' filename: "my-signature", // 仅当 type 为 'file' 时有效 }); console.log("Saved result:", result); }, clear() { this.$refs.signature.clear(); }, undo() { this.$refs.signature.undo(); }, redo() { this.$refs.signature.redo(); }, addWaterMark() { this.$refs.signature.addWaterMark({ text: "Vue2 Signature", font: "30px Arial", style: "all", fillStyle: "rgba(255, 0, 0, 0.2)", strokeStyle: "rgba(255, 0, 0, 0.2)", x: 100, y: 100, }); }, trim() { // 获取裁剪掉空白后的 Base64 const url = this.$refs.signature.toTrimmedDataURL("image/png"); console.log("Trimmed URL:", url); }, toggleDisabled() { this.disabled = !this.disabled; } }, }; </script> ``` ## 续签使用方式和保存方案 ### 续签使用方式 续签功能允许用户在已有签名的基础上继续签名,而无需重新开始Vue2 Signature 组件提供了多种方式实现续签功能: #### 1. 使用原始笔画数据(推荐) 使用原始笔画数据是实现续签功能的最佳方式,因为它可以保持签名的矢量特性,续签时笔触更加自然流畅 ```vue <template> <div class="signature-container"> <Vue2Signature ref="signature" :sigOption="options" w="100%" h="400px" /> <div class="actions"> <button @click="saveStrokeData">保存笔画数据</button> <button @click="loadStrokeData">加载笔画数据(续签)</button> <button @click="clear">清空</button> </div> </div> </template> <script> export default { data() { return { options: { penColor: "rgb(0, 0, 0)", backgroundColor: "rgb(255, 255, 255)" }, savedStrokeData: null }; }, methods: { saveStrokeData() { // 保存原始笔画数据 this.savedStrokeData = this.$refs.signature.toData(); console.log("笔画数据已保存"); // 可以将数据保存到 localStorage 或服务器 // localStorage.setItem('signature-stroke-data', JSON.stringify(this.savedStrokeData)); }, loadStrokeData() { // 加载笔画数据实现续签 if (this.savedStrokeData) { this.$refs.signature.fromData(this.savedStrokeData); console.log("笔画数据已加载,可继续签名"); } }, clear() { this.$refs.signature.clear(); this.savedStrokeData = null; } } }; </script> ``` #### 2. 使用图片 URL 如果您只需要简单的续签功能,也可以使用图片 URL 实现 ```vue <template> <div class="signature-container"> <Vue2Signature ref="signature" :sigOption="options" :defaultUrl="savedSignatureUrl" w="100%" h="400px" /> <div class="actions"> <button @click="saveSignature">保存签名</button> <button @click="clear">清空</button> </div> </div> </template> <script> export default { data() { return { options: { penColor: "rgb(0, 0, 0)", backgroundColor: "rgb(255, 255, 255)" }, savedSignatureUrl: null }; }, methods: { saveSignature() { // 保存签名为 Base64 URL this.savedSignatureUrl = this.$refs.signature.toDataURL(); console.log("签名已保存"); }, clear() { this.$refs.signature.clear(); this.savedSignatureUrl = null; } } }; </script> ``` ### 不续签保存时的图片方案 当用户完成签名后,Vue2 Signature 组件提供了多种保存图片的方案,以满足不同的业务需求: #### 1. 保存为 Base64 字符串 ```javascript // 获取完整签名的 Base64 字符串 const base64Data = this.$refs.signature.save("image/png", { type: "base64" }); // 获取裁剪空白后的 Base64 字符串 const trimmedBase64 = this.$refs.signature.toTrimmedDataURL("image/png"); ``` #### 2. 保存为 Blob 对象 ```javascript // 获取完整签名的 Blob 对象 const blobData = this.$refs.signature.save("image/png", { type: "blob" }); // 可用于上传到服务器 const formData = new FormData(); formData.append("signature", blobData, "signature.png"); // axios.post("/api/upload", formData); ``` #### 3. 保存为 File 对象 ```javascript // 获取完整签名的 File 对象 const fileData = this.$refs.signature.save("image/png", { type: "file", filename: "my-signature" }); // 可用于上传到服务器 const formData = new FormData(); formData.append("signature", fileData); // axios.post("/api/upload", formData); ``` #### 4. 保存为 SVG 格式 ```javascript // 获取 SVG 格式的签名数据 const svgData = this.$refs.signature.toSVG(); ``` #### 5. 保存原始笔画数据(用于后续续签) ```javascript // 获取原始笔画数据 const strokeData = this.$refs.signature.toData(); // 保存到 localStorage 或服务器 localStorage.setItem("signature-stroke-data", JSON.stringify(strokeData)); ``` ### 最佳实践 1. **对于需要续签的场景**- 推荐使用 `toData()` 和 `fromData()` 方法保存和恢复原始笔画数据 - 这种方式可以保持签名的矢量特性,续签时笔触更加自然 2. **对于不需要续签的场景**- 根据实际需求选择合适的保存格式: - Base64:适合直接嵌入 HTML 或存储在数据库中 - Blob/File:适合上传到服务器 - SVG:适合需要无损缩放的场景 - 考虑使用 `toTrimmedDataURL()` 方法获取裁剪后的图片,减少文件大小 3. **性能优化**- 保存大量签名时,建议使用 Blob/File 格式而不是 Base64 - 考虑压缩图片质量,尤其是 JPEG 格式 ## 📖 API 文档 ### Props (属性) | 属性名 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | `sigOption` | `Object` | `{}` | 传递给 `signature_pad` 的配置项默认包含:<br>`backgroundColor`: "rgb(255,255,255)"<br>`penColor`: "rgb(0, 0, 0)"<br>`minWidth`: 0.5<br>`maxWidth`: 2.5 | | `w` | `String` | `"100%"` | 画布宽度,支持 `px` 或百分比 | | `h` | `String` | `"100%"` | 画布高度,支持 `px` 或百分比 | | `clearOnResize` | `Boolean` | `false` | 当窗口大小改变导致画布重置大小时,是否清空画布内容默认会尝试保留内容 | | `waterMark` | `Object` | `{}` | 初始化时添加的水印配置对象详见 [WaterMarkOption](#watermarkoption-水印配置) | | `disabled` | `Boolean` | `false` | 是否禁用签名板(只读模式) | | `defaultUrl` | `String` | `""` | 初始加载的图片 URL,会绘制在画布上 | ### Methods (方法) 通过 `ref` 调用组件方法: `this.$refs.yourRefName.methodName()` | 方法名 | 参数 | 返回值 | 说明 | | --- | --- | --- | --- | | `save(format, options)` | `format`: string (默认 "image/png")<br>`options`: [SaveOption](#saveoption-保存配置) | `string \| Blob \| File` | 保存签名根据 `options.type` 返回不同类型的数据 | | `clear()` | - | `void` | 清空画布和历史记录 | | `isEmpty()` | - | `boolean` | 判断画布是否为空 | | `undo(steps)` | `steps`: number (默认 1) | `void` | 撤销上一步或多步操作 | | `redo(steps)` | `steps`: number (默认 1) | `void` | 重做上一步或多步操作 | | `toData()` | - | `Array` | 获取签名的原始笔画数据(PointGroups) | | `fromData(data)` | `data`: Array | `void` | 从原始笔画数据恢复签名 | | `toDataURL(format, options)` | 同 `save` | `string \| Blob \| File` | 生成签名的 Data URL 或文件对象 | | `fromDataURL(url, options)` | `url`: string<br>`options`: Object | `Promise` | 从图片 URL 加载内容到画布 | | `toSVG(options)` | `options`: Object | `string` | 获取 SVG 格式的签名数据 | | `addWaterMark(options)` | `options`: [WaterMarkOption](#watermarkoption-水印配置) | `void` | 在画布上添加水印 | | `trim(options)` | `options`: [TrimOption](#trimoption-裁剪配置) | `{ canvas, dataUrl, bounds }` | 计算并返回去除空白后的签名数据 | | `toTrimmedDataURL(format, options)` | `format`: string<br>`options`: Object | `string` | 直接获取裁剪空白后的 Data URL | | `getOptions()` | - | `Object` | 获取当前 `signature_pad` 的配置选项 | | `getInstance()` | - | `SignaturePad` | 获取内部 `signature_pad` 实例 | ### Events (事件) | 事件名 | 参数 | 说明 | | --- | --- | --- | | `ready` | `SignaturePad` 实例 | 组件挂载完成且 SignaturePad 初始化后触发 | | `begin` | - | 开始绘制一笔时触发 | | `end` | - | 结束绘制一笔时触发 | | `beginStroke` | `event` | 笔画开始前触发(原生事件) | | `endStroke` | `event` | 笔画结束时触发(原生事件) | | `beforeUpdateStroke` | `event` | 笔画更新前触发 | | `afterUpdateStroke` | `event` | 笔画更新后触发 | ### 配置对象说明 #### SaveOption (保存配置) 用于 `save()` 和 `toDataURL()` 方法的第二个参数 ```javascript { quality: 0.8, // 图片质量 (0-1),仅适用于 image/jpeg 或 image/webp type: "base64", // 输出类型: "base64" (默认) | "blob" | "file" filename: "signature" // 当 type 为 "file" 时及其文件名 (不含后缀) } ``` #### WaterMarkOption (水印配置) 用于 `waterMark` 属性或 `addWaterMark()` 方法 ```javascript { text: "水印文本", // 水印文字内容 font: "20px sans-serif", // 字体样式 style: "fill", // 绘制风格: "fill" (填充) | "stroke" (描边) | "all" (填充+描边) fillStyle: "#333", // 填充颜色 strokeStyle: "#333", // 描边颜色 x: 20, // X 轴坐标 y: 20, // Y 轴坐标 sx: 40, // 描边偏移量 X (仅 style 为 'all' 或 'stroke' 时有效) sy: 40 // 描边偏移量 Y } ``` #### TrimOption (裁剪配置) 用于 `trim()` 方法 ```javascript { backgroundColor: "rgb(255, 255, 255)", // 指定背景色,用于计算空白区域。不传则自动获取当前背景色。 format: "image/png", // 返回的 dataUrl 格式 encoderOptions: 1.0 // 返回的 dataUrl 质量 } ``` ## 许可证 MIT