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 或小程序环境的独立适配包。
相关推荐
贵州数擎科技有限公司3 小时前
霓虹沙尘暴的 Three.js 实现
前端·webgl
一只叁木Meow3 小时前
电商 SKU 选择器:用算法实现优雅的用户交互
前端·javascript·算法
Aolith3 小时前
事件驱动设计:我如何为校园论坛实现消息通知功能
前端·vue.js
代码煮茶3 小时前
Vue3 Mock 数据实战 | 用 Mockjs + vite-plugin-mock 搭建前端独立开发环境
javascript·vue.js
yingyima3 小时前
GitHub Actions 定时任务 schedule 踩坑实录:核心语法与实战技巧
前端
代码煮茶3 小时前
CSS 单位完全指南:px、em、rem、vw、vh、clamp 详解
前端·css
KaMeidebaby3 小时前
卡梅德生物技术快报|PROTAC 药物降解蛋白原理及数据库平台开发全流程
前端·数据库·其他·百度·新浪微博
玄米乌龙茶1234 小时前
LLM成长笔记(七): AI 应用框架与编排
前端·人工智能·笔记
芯芯点灯5 小时前
gd32f303烧录提示Flash Timeout. Reset the Target and try it again.;
开发语言·前端·javascript