vue实践:构建高效的电子签名功能

前言

在现代数字化时代,电子签名成为了一种方便、高效且安全的签署文件的方式。本文将介绍电子签名的原理和实现方法,帮助你快速掌握这一重要的工具。


电子签名是什么?

电子签名是一种数字化的签名方式,用于验证和确认电子文档、合同或其他电子信息的真实性和完整性。它是传统纸质签名的数字化替代品,具有更高的效率、便捷性和安全性。大家看下面这个例子就会一目了然了。


一、手动实现一个简单的电子签名

下面的示例中,我们使用了 Canvas 元素来绘制用户的签名。当用户按下鼠标左键时,startDrawing 方法会被调用,开始绘制路径。当用户移动鼠标时,draw 方法会被调用,绘制路径。当用户释放鼠标左键时,stopDrawing 方法会被调用,停止绘制路径。点击"清除"按钮会清除 Canvas 上的内容,点击"保存"按钮会将签名保存为 Base64 编码的图片数据。

<template>
  <div>
    <canvas ref="canvas" @mousedown="startDrawing" @mousemove="draw" @mouseup="stopDrawing"></canvas>
    <div>
      <button @click="clearCanvas">清除</button>
      <button @click="saveSignature">保存</button>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isDrawing: false, // 是否正在绘制
      context: null, // Canvas上下文
    };
  },
  mounted() {
    this.context = this.$refs.canvas.getContext("2d"); // 获取Canvas上下文
    this.$refs.canvas.width = 500; // 设置Canvas的宽度
    this.$refs.canvas.height = 300; // 设置Canvas的高
  },
  methods: {
    // 鼠标按下时触发
    startDrawing(event) {
      this.isDrawing = true; // 开始绘制
      const { offsetX, offsetY } = event; // 获取鼠标相对于Canvas的偏移量
      this.context.beginPath(); // 开始新的路径
      this.context.moveTo(offsetX, offsetY); // 将路径移动到鼠标位置
    },
    // 当鼠标在 Canvas 上移动时触发
    draw(event) {
      if (!this.isDrawing) return; // 如果没有在绘制中,则返回
      const { offsetX, offsetY } = event; // 获取鼠标相对于Canvas的偏移量
      this.context.lineTo(offsetX, offsetY); // 绘制路径
      this.context.stroke(); // 绘制路径的边框
    },
    // 当鼠标松开时触发,用于停止绘制签名
    stopDrawing() {
      this.isDrawing = false; // 停止绘制
    },
    // 清除
    clearCanvas() {
      this.context.clearRect(
        0,
        0,
        this.$refs.canvas.width,
        this.$refs.canvas.height
      ); // 清除Canvas上的内容
    },
    // 保存
    saveSignature() {
      const dataURL = this.$refs.canvas.toDataURL(); // 获取签名图片的Base64编码
      // 在这里可以将dataURL发送到服务器保存,或者进行其他操作
      console.log(dataURL); // 输出签名的Base64编码到控制台
    },
  },
};
</script>
<style scoped>
canvas {
  border: 1px solid red;
}
</style>

实现效果
在这里插入图片描述


二、vue-esign 插件

vue-esign 是一个基于 vue.js 框架的电子签名组件库,它提供了一套现成的 UI 组件,包括签名面板、工具栏等,可以方便地在 vue.js 应用中实现电子签名功能。

2.1 安装

npm install vue-esign --save

2.2 引用

  • 全局引用

    import vueEsign from 'vue-esign'
    Vue.use(vueEsign)
    
  • 局部引用

    import vueEsign from 'vue-esign'
    components: { vueEsign }
    

2.3 使用

<template>
  <div class="box">
    <vue-esign ref="esign" :width="300" :height="150" :isCrop="isCrop" :lineWidth="lineWidth" :lineColor="lineColor"
      :bgColor.sync="bgColor" />
    <div>
      <button @click="handleReset">清空画板</button>
      <button @click="handleGenerate">生成图片</button>
    </div>
    <img :src="resultImg" alt="">
  </div>
</template>

<script>
import vueEsign from "vue-esign";
export default {
  components: { vueEsign },
  data() {
    return {
      lineWidth: 6,
      lineColor: "#000000",
      bgColor: "",
      resultImg: "",
      isCrop: false,
    };
  },
  mounted() {},
  methods: {
    handleReset() {
      this.$refs.esign.reset();
    },
    handleGenerate() {
      this.$refs.esign
        .generate({ format: "png", quality: 0.8 })
        .then((res) => {
          this.resultImg = res;
        })
        .catch((err) => {
          console.error(err);
          alert("生成图片失败:" + err.message);
        });
    },
  },
};
</script>
<style scoped>
.box {
  width: 300px;
  height: 150px;
  border: 1px solid red;
}
</style>

实现效果

在这里插入图片描述

此外,vue-esign 插件还支持画笔粗细自定义、画笔颜色自定义等等,感兴趣的同学可以看下面的属性试试。

2.4 常用的属性

属性类型默认值描述
widthNumber800画布宽度,即导出图片的宽度
heightNumber300画布高度,即导出图片的高度
lineWidthNumber4画笔粗细
lineColorString#000000画笔颜色
bgColorString画布背景色,为空时画布背景透明,支持多种格式 ‘#ccc’,‘#E5A1A1’,‘rgb(229, 161, 161)’,‘rgba(0,0,0,.6)’,‘red’
isCropBooleanfalse是否裁剪,在画布设定尺寸基础上裁掉四周空白部分
isClearBgColorBooleantrue清空画布时(reset)是否同时清空设置的背景色(bgColor)
formatStringimage/png生成图片格式 image/jpeg(jpg格式下生成的图片透明背景会变黑色请慎用或指定背景色)、 image/webp
qualityNumber1生成图片质量;在指定图片格式为 image/jpeg 或 image/webp的情况下,可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92。其他参数会被忽略。

三、vue-signature-pad 插件

vue-signature-pad 同样是一个基于 vue.js 框架的电子签名组件库,它提供了一个可定制的签名面板,可以方便地在 vue.js 应用中实现电子签名功能。

注意: 如果仍在使用 vue2 ,请安装 2.0.5 版本,对于 vue3,可以安装最新的发布版本。

3.1 安装

npm i vue-signature-pad@2.0.5

3.2 全局引用

import VueSignature from "vue-signature-pad";
Vue.use(VueSignature);

3.3 使用

<template>
  <div class="box">
    <VueSignaturePad width="300px" height="150px" ref="signaturePad" />
    <div>
      <button @click="save">保存</button>
      <button @click="undo">撤销</button>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {};
  },
  mounted() {},
  methods: {
    // 撤销操作
    undo() {
      this.$refs.signaturePad.undoSignature();
    },
    // 保存操作
    save() {
      const { isEmpty, data } = this.$refs.signaturePad.saveSignature();
      console.log(data);
    },
  },
};
</script>
<style scoped>
.box {
  width: 300px;
  height: 150px;
  border: 1px solid red;
}
</style>

实现效果

在这里插入图片描述

3.4 常用的属性

属性类型默认值描述
widthString100%画布宽度
heightString100%画布高度
optionsObject{}设置画笔的选项,包括线条颜色、宽度、透明度等
imagesArray[]设置背景图片。可以是 [‘1.png’, ‘2.png’] 或者 [{ src: ‘1.png’, x: 0, y: 0 }, { src: ‘2.png’, x: 0, y: 10 }]
customStyleObject{}设置画布的自定义样式。可以是一个CSS样式对象
scaleToDevicePixelRatioBooleantrue设置是否将画布缩放到设备像素比

3.5 常用的方法

方法参数描述
saveSignature(type, encoderOptions)(String, Number)保存当前的签名,并返回一个包含签名是否为空和签名数据的对象
undoSignature()-撤销上一步的签名操作
clearSignature()-清除当前的签名
mergeImageAndSignature(signature)Object 或者 String将指定的背景图片与当前的签名合并
addImages(images)Array添加多个背景图片
lockSignaturePad()-锁定签名画布,禁止用户进行签名操作
openSignaturePad()-解锁签名画布,允许用户进行签名操作
getPropImagesAndCacheImages()-获取图像的信息
clearCacheImages()-清除缓存的图片
fromDataURL(data, options, callback)(String, Object, Callback)从指定的DataURL加载签名数据
fromData(data)String从指定的数据加载签名数据
toData()-获取当前的签名数据
isEmpty()-检查当前的签名是否为空

完整功能代码

<template>
  <div class="box">
    <!-- VueSignaturePad 组件 -->
    <VueSignaturePad :width="width" :height="height" :options="options" :images="images" :customStyle="customStyle"
      :scaleToDevicePixelRatio="scaleToDevicePixelRatio" ref="signaturePad" />
    <div>
      <!-- 操作按钮 -->
      <button @click="save">保存</button>
      <button @click="undo">撤销</button>
      <button @click="clear">清除</button>
      <button @click="mergeImage">合并图片</button>
      <button @click="addImages">添加图片</button>
      <button @click="lock">锁定</button>
      <button @click="unlock">解锁</button>
      <button @click="getData">获取数据</button>
      <button @click="isEmpty">是否为空</button>
      <button @click="getPropImagesAndCacheImages">获取并缓存背景图片</button>
      <button @click="clearCacheImages">清除缓存的背景图片</button>
      <button @click="loadSignatureFromDataURL">从 Data URL 加载签名</button>
      <button @click="loadSignatureFromData">从 JSON 数据加载签名</button>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      width: "1000px",
      height: "500px",
      options: {
        minWidth: 2, // 画笔最小宽度
        maxWidth: 5, // 画笔最大宽度
        throttle: 16, // 画笔移动事件的时间间隔,单位为毫秒
        minDistance: 5, // 画笔移动的最小距离,单位为像素
        backgroundColor: "rgba(255, 255, 255, 0)", // 画布背景颜色
        penColor: "red", // 画笔颜色
        velocityFilterWeight: 0.7, // 画笔速度过滤器的权重
        onBegin: () => {}, // 开始签名时的回调函数
        onEnd: () => {}, // 结束签名时的回调函数
      },
      images: [],
      customStyle: {
        signatureCanvas: {
          border: "1px solid #ccc", // 画布边框
          borderRadius: "5px", // 画布圆角
        },
        signaturePad: {
          boxShadow: "0 0 5px rgba(0, 0, 0, 0.1)", // 画笔阴影
        },
      },
      scaleToDevicePixelRatio: true,
    };
  },
  methods: {
    // 保存签名
    save() {
      const { isEmpty, data } = this.$refs.signaturePad.saveSignature();
      console.log("签名是否为空:", isEmpty);
      console.log("签名数据:", data);
    },
    // 撤销签名
    undo() {
      this.$refs.signaturePad.undoSignature();
    },
    // 清除签名
    clear() {
      this.$refs.signaturePad.clearSignature();
    },
    // 合并图片和签名
    mergeImage() {
      const image = "image.jpg"; // 替换为你的背景图片路径
      this.$refs.signaturePad.mergeImageAndSignature(image);
    },
    // 添加图片
    addImages() {
      const images = ["image.jpg", "image.jpg"]; // 替换为你的背景图片路径数组
      this.$refs.signaturePad.addImages(images);
    },
    // 锁定签名画布
    lock() {
      this.$refs.signaturePad.lockSignaturePad();
    },
    // 解锁签名画布
    unlock() {
      this.$refs.signaturePad.openSignaturePad();
    },
    // 获取签名数据
    getData() {
      const data = this.$refs.signaturePad.toData();
      console.log("获取签名数据:", data);
    },
    // 检查签名是否为空
    isEmpty() {
      const empty = this.$refs.signaturePad.isEmpty();
      if (!empty) {
        alert("画布不为空!");
      } else {
        alert("画布为空!");
      }
    },
    // 获取并缓存背景图片
    getPropImagesAndCacheImages() {
      const images = ["image1.jpg", "image2.jpg"]; // 替换为你的背景图片路径数组
      this.$refs.signaturePad.getPropImagesAndCacheImages(images);
    },
    // 清除缓存的背景图片
    clearCacheImages() {
      this.$refs.signaturePad.clearCacheImages();
    },
    // 从 Data URL 加载签名
    loadSignatureFromDataURL() {
      const dataURL = "data:image/png;base64,iVBORw0KG..."; // 替换为你的 Data URL
      this.$refs.signaturePad.fromDataURL(dataURL);
    },
    // 从 JSON 数据加载签名
    loadSignatureFromData() {
      const signatureData = {
        width: 500,
        height: 500,
        data: [
          {
            color: "#000",
            points: [
              { x: 100, y: 100 },
              { x: 200, y: 200 },
              { x: 300, y: 300 },
            ],
          },
          {
            color: "#f00",
            points: [
              { x: 400, y: 400 },
              { x: 450, y: 450 },
              { x: 500, y: 500 },
            ],
          },
        ], //替换你的数据
      };
      const pointGroups = signatureData.data;
      this.$refs.signaturePad.fromData(pointGroups);
    },
  },
};
</script>
<style scoped>
.box {
  width: 1000px;
  height: 500px;
  border: 1px solid red;
}
</style>

四、vue-esign 和 vue-signature-pad 的区别?

4.1 共同点

  • 兼容 PC 和 移动端;
  • 同时支持 vue2vue3;
  • 画布自适应屏幕大小变化(窗口缩放、屏幕旋转时画布无需重置,自动校正坐标);
  • 自定义画布尺寸,画笔粗细、颜色,画布背景色。

4.2 不同点

  • vue-signature-pad 带笔压功能,可以根据笔的速度和方向来调整线条的粗细,不是固定粗细的,vue-esign 不支持此功能;
  • vue-signature-padvue2vue3 依赖安装版本不同;vue-esign 都版本向下兼容,不需要区分 vue2vue3;
  • vue-signature-pad 支持单步撤回,vue-esign 不支持此功能。

笔压对比效果

左边是 vue-signature-pad 插件,可以看到画笔线条不是固定粗细的,右边是 vue-esign 插件,线条是固定的粗细。
在这里插入图片描述


相关推荐

⭐ 浅谈 JSON 对象和 FormData 相互转换,打通前端与后端的通信血脉

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/358510.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ES集群节点、主从、负责均衡

集群 节点介绍 Elasticsearch的协调节点并不是master节点。在Elasticsearch集群中&#xff0c;有几种不同类型的节点&#xff0c;其中包括&#xff1a; Master节点&#xff1a;负责集群范围内的管理和控制&#xff0c;例如创建或删除索引&#xff0c;决定哪些分片分配给哪个…

vxe-table从2.0升级到3.0,vxe-table-plugin-virtual-tree虚拟滚动失效

问题&#xff1a;系统一直使用的vxe-table2.0&#xff0c;vxe-table2.0不支持树的虚拟滚动&#xff0c;为了解决这个问题&#xff0c;引入了vxe-table-plugin-virtual-tree插件&#xff0c;现在系统vxe-table升级3.0&#xff0c;vxe-table-plugin-virtual-tree的虚拟滚动失效了…

Python第三方扩展库Matplotlib

Python第三方扩展库Matplotlib Matplotlib 是第三方库&#xff0c;不是Python安装程序自带的库&#xff0c;需要额外安装&#xff0c;它是Python的一个综合性的绘图库&#xff0c;提供了大量的绘图函数用于创建静态、动态、交互式的图形和数据可视化&#xff0c;可以帮助用户创…

Android App开发-简单控件(1)——文本显示

本章介绍了App开发常见的几类简单控件的用法&#xff0c;主要包括&#xff1a;显示文字的文本视图、容纳视图的常用布局、响应点击的按钮控件、显示图片的图像视图等。然后结合本章所涉及的知识&#xff0c;完成一个实战项目“简单计算器”的设计与实现。 1.1 文本显示 本节介绍…

(九)springboot实战——springboot3下的webflux项目参数验证及其全局参数验证异常处理

前言 在上一节内容中&#xff0c;我们介绍了如何在webflux项目中自定义实现一个全局的异常处理器ErrorWebExceptionHandler&#xff0c;正常情况下其可以处理我们系统的运行时异常&#xff0c;但是无法处理参数验证的异常WebExchangeBindException&#xff0c;所以这里提供另外…

彻底解决 MAC Android Studio gradle async 时出现 “connect timed out“ 问题

最近在编译一个比较老的项目&#xff0c;git clone 之后使用 async 之后出现一下现象&#xff1a; 首先确定是我网络本身是没有问题的&#xff0c;尝试几次重新 async 之后还是出现问题&#xff0c;网上找了一些方法解决了本问题&#xff0c;以此来记录一下问题是如何解决的。 …

JavaWeb学习|Session

学习材料声明 所有知识点都来自互联网&#xff0c;进行总结和梳理&#xff0c;侵权必删。 引用来源&#xff1a;尚硅谷最新版JavaWeb全套教程,java web零基础入门完整版 Session 1、Session 就一个接口&#xff08;HttpSession&#xff09;。 2、Session 就是会话。它是用来…

虚拟化平台、主机

虚拟化技术介绍 一、常见虚拟化技术 二、虚拟化与云计算的关系 虚拟化是什么 虚拟化是一种技术&#xff0c;就是将不可拆分的实体资源变成可以自由划分的逻辑资源&#xff0c;从而实现资源的整合、隔离、在分配&#xff0c;云计算就是利用了虚拟化技术的这个特点 云计算是…

java框架面试篇

Spring框架 spring Bean线程安全问题 Scope注解 我们可以在bean的类上加Scope注解来声明这个Bean是单个实例还是多个实例。在默认情况下Bean是单个实例的&#xff0c;此时的注解中的属性默认为Scope("singleton")&#xff0c;Scope("prototype")则是一…

BP图片降噪MATLAB代码

BP(Back Propagation)神经网络是一种常用的深度学习模型,可以用于图像降噪。主要步骤包括: 构建BP神经网络模型。包括输入层、隐藏层和输出层。输入层大小与图像大小相同,输出层大小也与输入图像大小相同。隐藏层根据图像复杂度设定。 准备训练数据。使用干净图像作为输入,加…

WIN11 - WSL(Windows Subsystem for Linux) 安装教程

前言 WSL&#xff0c;即Windows Subsystem for Linux&#xff0c;是一种在Windows操作系统上运行Linux二进制文件的兼容层。该层提供了Linux环境和GNU工具&#xff0c;可以在Windows系统上运行Linux应用程序。WSL使得开发人员可以在Windows系统上使用Linux工具和命令行界面&am…

Web自动化—Cypress 测试框架概述

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号&#xff1a;互联网杂货铺&#xff0c;回复1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;薪资嘎嘎涨 Cypress 测试框架概述 1.1 Cypress 默认文件结构 在C…

漏洞原理远程命令执行

漏洞原理远程命令/代码执行 远程命令执行函数&#xff08;Remote Command Execution Function&#xff09;是指在一个网络环境中&#xff0c;通过远程执行命令来控制另一个计算机系统或设备的功能。 远程命令执行函数可以通过网络协议&#xff08;如SSH、Telnet、RPC等&#x…

苹果电脑哪款文件管理器好用?推荐QSpace Pro多窗格文件管理器

还在找好用的Mac文件管理器&#xff1f;苹果电脑哪款文件管理器好用&#xff1f;推荐QSpace Pro多窗格文件管理器&#xff0c;灵活且实用&#xff01; Mac软件下载安装&#xff1a;多窗格文件管理QSpace Pro 首先&#xff0c;我被QSpace的简洁和高效所吸引。它的界面设计非常清…

第九节HarmonyOS 常用基础组件13-TimePicker

1、描述 时间选择组件&#xff0c;根据指定参数创建选择器&#xff0c;支持选择小时以及分钟。默认以24小时的时间区间创建滑动选择器。 2、接口 TimePicker(options?: {selected?: Date}) 3、参数 selected - Date - 设置选中项的时间。默认是系统当前的时间。 4、属性…

代码随想录算法训练营第35天 | 860.柠檬水找零 + 406.根据身高重建队列 + 452.用最少数量的箭引爆气球

今日任务 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球 860.柠檬水找零 - Easy 题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 在柠檬水摊上&#xff0c;每一杯柠檬水的售价为 5 美元。顾客排队购买你的…

Backtrader 文档学习-Bracket Orders

Backtrader 文档学习-Bracket Orders 1. 概述 组合订单类型是一个非常宽泛的订单类别&#xff0c;只要brokder支持的订单类型都可以&#xff0c; 包括(Market, Limit, Close, Stop, StopLimit, StopTrail, StopTrailLimit, OCO)。 该功能用于回测&#xff0c;交互broker Brac…

VBA语言専攻介绍(更新)

VBA语言専攻简介 我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。我这里专注VBA&#xff0c;垂直度非常高&#xff0c;并和多个国际VBA网站&#xff08;英语系和德语系&#xff09;有互动及技术互通。您来到这里&#xff0c;就是进入到了一个绚烂的VBA世界&…

vue-computed 计算属性

一、computed 计算属性 在Vue应用中&#xff0c;在模板中双向绑定一些数据或者表达式&#xff0c;但是表达式如果过长&#xff0c;或者逻辑更为复杂 时&#xff0c;就会变得臃肿甚至难以维护和阅读&#xff0c;例如&#xff1a; <div>写在双括号中的表达式太长了,不利于阅…

【数据结构:顺序表】

文章目录 线性表顺序表1.1 顺序表结构的定义1.2 初始化顺序表1.3 检查顺序表空间1.4 打印1.5 尾插1.6 头插1.7 尾删1.8 头删1.9 查找1.10 指定位置插入1.11 删除指定位置数据1.12 销毁顺序表 数据结构(Data Structure)是计算机存储、组织数据的方式&#xff0c;指相互之间存在一…