vue2-signature
Version:
Vue 2 signature pad component
442 lines (371 loc) • 13.6 kB
Markdown
<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 端鼠标和移动端触摸操作
- 🎨 **高度可定制** - 支持自定义笔触颜色、宽度、背景色、画布尺寸等
- 💾 **丰富的导出功能** - 支持导出 Base64、Blob、File 对象,支持 PNG、JPEG、SVG 格式
- ✂️ **自动裁剪** - 支持自动裁剪签名周围的空白区域
- 🔄 **历史记录管理** - 内置撤销(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"
="onReady"
="onBegin"
="onEnd"
/>
<div class="actions">
<button ="save('base64')">保存为 Base64</button>
<button ="save('file')">保存为 File</button>
<button ="clear">清空</button>
<button ="undo">撤销</button>
<button ="redo">重做</button>
<button ="addWaterMark">添加水印</button>
<button ="trim">获取裁剪后数据</button>
<button ="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 ="saveStrokeData">保存笔画数据</button>
<button ="loadStrokeData">加载笔画数据(续签)</button>
<button ="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 ="saveSignature">保存签名</button>
<button ="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