vue-sign-canvas v2 重构复盘:从 Vue 2 签名板到 Vue 3 + TypeScript 组件库

vue-sign-canvas 最初是一个面向 Vue 2 的手写签名板组件,核心目标很直接:让用户可以在 PC 或移动端完成签名,并导出 base64 图片。随着使用场景变多,旧版本逐渐暴露出一些维护和能力边界上的问题,例如移动端触点偏移、空签名校验不够明确、回显后继续编辑不稳定、导出格式处理不完整,以及组件内部逻辑越来越难维护。

v2 版本选择直接做一次不兼容升级:基于 Vue 3、TypeScript 和 Vite 重新整理组件结构,同时把签名板常见的业务能力补齐。

为什么要做一次不兼容升级

签名板看起来只是一个 canvas 组件,但真实业务里经常会遇到这些要求:

  • 表单提交前必须判断用户是否真的签名。
  • 后端返回已有签名后,需要回显到画布,并允许继续补签。
  • 移动端和 PC 端都要可用,触点位置不能偏。
  • 高清屏导出不能模糊。
  • 用户误操作后需要撤销、重做。
  • 合同、确认单、练字等场景需要背景图或临摹稿。
  • JPEG 导出不能出现透明区域黑底。
  • TypeScript 项目需要完整类型提示。

这些能力如果继续堆在旧组件里,会让组件越来越难维护。v2 的目标不是只把 Vue 2 代码改到 Vue 3 能跑,而是重新定义组件的内部边界,让绘制、状态、导出、图层和对外 API 各自清晰。

技术栈升级

v2 使用了新的基础栈:

  • Vue 3
  • TypeScript
  • Vite
  • Pointer Events
  • ESM / UMD 构建产物
  • .d.ts 类型声明输出

这也意味着 v2 不再兼容 Vue 2 项目。如果项目仍然使用 Vue 2,可以继续安装旧版本:

bash 复制代码
npm i sign-canvas@1

组件结构调整

v2 将核心逻辑拆成了更容易维护的几部分:

  • constants.ts:集中维护配置项、默认值和类型。
  • useSignCanvas.ts:管理组件状态、事件、笔迹历史和对外 API。
  • utils/canvas.ts:处理 canvas 绘制、图片加载、导出、旋转和图层绘制。
  • index.vue:保留组件模板和事件绑定,避免把所有逻辑塞进单文件组件。

这样的拆分让新增功能更直接。例如背景图、临摹图和导出旋转都属于 canvas 能力,放在 utils/canvas.ts;撤销、重做、回显和签名状态属于组件状态,放在 useSignCanvas.ts

输入事件:统一 PC 和移动端

旧版本常见的问题之一是移动端触摸坐标容易出现偏移。v2 改为使用 Pointer Events 统一鼠标、触摸和触控笔输入。

组件会通过 canvas 的 getBoundingClientRect() 计算真实的 CSS 像素坐标,再结合 DPR 绘制到真实像素画布上。这样可以同时保证输入位置准确和高分屏清晰。

空签名判断

业务里经常需要判断"用户是否真的签名"。v2 明确区分真实签名内容和辅助图层:

  • 用户绘制的笔迹会计入签名状态。
  • fromDataURL() 回显的已有签名会计入签名状态。
  • 背景色、边框、辅助线、背景图和临摹层不会计入签名状态。

因此可以直接使用:

ts 复制代码
if (signCanvasRef.value?.isEmpty()) {
  return;
}

也可以获取更完整的状态:

ts 复制代码
const status = signCanvasRef.value?.getSignatureStatus();

回显后继续编辑

v2 新增了 fromDataURL(),支持把已有签名图片回显到画布:

ts 复制代码
await signCanvasRef.value?.fromDataURL(base64);

回显图片会作为签名内容的一部分参与导出,用户也可以在回显图上继续绘制。这个能力适合"草稿签名""补签""编辑已有签名"等场景。

同时组件也支持通过 v-modelimage 传入已有图片,完成自动回显。

撤销和重做

v2 增加了笔迹历史。历史记录按"每次下笔"保存,而不是按每一个线段保存。这样用户连续写一笔时,撤销会更符合直觉。

ts 复制代码
signCanvasRef.value?.undo();
signCanvasRef.value?.redo();

默认也支持快捷键:

  • Ctrl / Command + Z:撤销
  • Ctrl / Command + Y:重做
  • Ctrl / Command + Shift + Z:重做

如果页面中有多个签名板,快捷键只作用于当前获得焦点的画布,避免互相干扰。

背景图合成

一些业务需要在固定模板上签名,例如合同、确认单、授权书。v2 新增了背景图配置:

ts 复制代码
const options = {
  backgroundImage: contractBase64,
  backgroundImageFit: 'cover',
  backgroundImageOpacity: 1
};

背景图会显示在画布上,并合成进最终导出的图片,但不会被视为用户已经签名。

描写和临摹

v2 增加了独立的临摹引导层,可以通过 guideEnabled 开启或关闭。

文字临摹:

ts 复制代码
const options = {
  guideEnabled: true,
  guideText: '张三',
  guideFont: '700 96px serif',
  guideTextColor: '#101010',
  guideTextOpacity: 0.16
};

图片临摹:

ts 复制代码
const options = {
  guideEnabled: true,
  guideImage: '/trace-template.png',
  guideImageFit: 'contain',
  guideImageOpacity: 0.24
};

临摹层同样只是一层辅助图层,不会影响空签名判断,也不会进入撤销历史。

导出旋转

部分移动端业务会要求横向签名后导出竖图,或者反过来。v2 新增了 exportRotate

ts 复制代码
const options = {
  exportRotate: 90
};

支持的角度为:

  • 0
  • 90
  • 180
  • 270

这个配置只影响导出的图片方向,不改变页面上正在绘制的画布方向。

JPEG 白底导出

JPEG 不支持透明通道。如果直接把透明 canvas 导出为 JPEG,部分环境会出现黑底。v2 在 JPEG 导出时会自动铺底色:

ts 复制代码
const options = {
  imgType: 'jpeg',
  jpegBgColor: '#fff'
};

这样可以避免透明区域在导出后变黑。

Demo 工作台

v2 也重写了 demo 页面。新的 demo 不只是展示一个签名框,而是一个完整的调试工作台:

  • 桌面端预览
  • 移动端预览
  • 画布参数调节
  • 画笔参数调节
  • 背景图配置
  • 描写/临摹配置
  • 导出格式配置
  • 撤销和重做
  • 导出结果预览

在线预览地址:

text 复制代码
https://langyuxiansheng.github.io/vue-sign-canvas/

桌面端预览:

移动端预览:

完整参数和导出预览:

迁移建议

如果你正在从 1.x 升级到 2.x,需要重点关注:

  1. Vue 2 项目不能直接升级到 v2,需要先升级到 Vue 3。
  2. 组件使用方式推荐改为 Vue 3 v-model
  3. 如果项目里使用旧方法名,v2 保留了部分兼容别名,例如 canvasClear()saveAsImg()dealImage()
  4. 新项目建议优先使用语义更清晰的方法:clear()toDataURL()fromDataURL()
  5. 如果依赖 uni-app 小程序或 App 端,不建议直接使用 Web 主包,应单独做平台适配。

总结

v2 的重点不是"能跑在 Vue 3",而是把签名板从一个简单 canvas 示例升级为更稳定的 Vue 3 组件库。它补齐了签名业务里常见的能力:空签名校验、回显编辑、撤销重做、背景合成、临摹引导、导出旋转和 TypeScript 类型支持。

后续如果继续扩展,可以围绕两个方向推进:

  • 更强的笔迹数据持久化和回放能力。
  • 面向 uni-app 或小程序环境的独立适配包。
相关推荐
weixin_382395238 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__8 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.9 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~10 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华10 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子13 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅13 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni13 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学14 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端