vue前端项目中实现电子签名功能(附完整源码)

ops/2024/12/27 7:52:05/

文章目录

    • 一、具体思路
    • 二、所需依赖
    • 三、添加签名面板
      • 2.1 canvas 转base64
      • 2.2 电子签名等比例缩小
    • 四、html转cavas(原始文档)
    • 五、合成图片
    • 六、效果测试
    • 七、完整源码

一、具体思路

在vue项目中使用以下步骤思路去实现:

  1. 起初的原始文档的格式都转成图片格式来处理;

  2. 电子签名的模板转成base64

  3. 前端将文档的样式和电子签名的模板合成一张图片,进行预览

通过原始图片文档与电子签名的图片进行合并,期间需要调整签名base64的位置和缩放比例,然后添加合并到原始文档,最终形成签名后的文档。

二、所需依赖

npm i signature_pad@4.2.0npm i html2canvas

signature_pad 签名板 https://www.npmjs.com/package/signature_pad
html2canvas html转cavas https://www.npmjs.com/package/html2canvas

三、添加签名面板

javascript">        <div class="sign-box" style="width:300px;height:200px;padding: 10px; margin:10px;background-color: rgb(221 216 216);"><p><span style="color: #f00;">*</span>签名版<span style="color: #f00;">*</span></p><div><canvas id="signCanvas"/></div><button type="default" @click="clear()">清除</button><button type="default" @click="review()">游览</button><button aria-placeholder="添加签名到文件" type="default" @click="submit()">提交</button></div>
javascript">import SignaturePad from 'signature_pad'
javascript">    mounted() {const canvas = document.getElementById('signCanvas')this.signatureExample = new SignaturePad(canvas, { penColor: 'rgb(0, 0, 0)' })  //penColor   笔的颜色},

在这里插入图片描述
发现我鼠标所在的位置跟落笔产生了偏移 需要调用一下这个 adjustSignatureImgPos这个方法

javascript">        //校正签名位置偏移adjustSignatureImgPos() {const canvas = document.getElementById('signCanvas')const ratio = Math.max(window.devicePixelRatio || 1, 1) // 清除画布canvas.width = canvas.offsetWidth * ratiocanvas.height = canvas.offsetHeight * ratiocanvas.getContext('2d').scale(ratio, ratio)},
javascript">    mounted() {const canvas = document.getElementById('signCanvas')this.signatureExample = new SignaturePad(canvas, { penColor: 'rgb(0, 0, 0)' })  //penColor   笔的颜色this.adjustSignatureImgPos()},

在这里插入图片描述

2.1 canvas 转base64

javascript">this.signatureimgSrc =this.signatureExample.toDataURL('image/png')   //得到了就是base64的   

打印输入如下:
在这里插入图片描述

2.2 电子签名等比例缩小

把生成的电子签名等比例缩小

传入我们电子签名的base64,然后生成一个新元素image ,改变它的大小,然后在通过canvas转成base64,在return 出来

我们需要使用Promise去异步处理他,并拿到返回的新base64

javascript">        // 绘制的canvas 进行缩放并转为base64resizeImage(src) {return new Promise((resolve) => {const img = new Image()img.src = srcimg.onload = () => {const originalWidth = img.widthconst originalHeight = img.heightconst scaleFactor = 0.5 // 缩放的倍数const resizedWidth = originalWidth * scaleFactorconst resizedHeight = originalHeight * scaleFactorconst canvas = document.createElement('canvas')canvas.width = resizedWidthcanvas.height = resizedHeightconst ctx = canvas.getContext('2d')ctx.drawImage(img, 0, 0, resizedWidth, resizedHeight)const base64 = canvas.toDataURL('image/png')resolve(base64)}})},

在这里插入图片描述

效果如下:

在这里插入图片描述

四、html转cavas(原始文档)

我们需要把html编写的文档转成base64
这个我们用html2canvas 这个插件:

javascript">import html2canvas from 'html2canvas'
javascript">html2canvas(document.querySelector("#capture")).then(canvas => {this.htmlimgUrl = canvas.toDataURL("image/png"); // 将canvas转换成img的src流
});

五、合成图片

接下来我们需要将html文档和电子签名模板,合成一张图片

写一个合并图片的方法:

传入两个参数,分别是原始图片文档和电子签名图片文档;

javascript">        //合并图片mergeimg(imgUrl,signatureimgSrc){// 创建一个 canvas 元素const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');// 创建两个图像对象const img1 = new Image();const img2 = new Image();// 设置图像的 src 属性为 Base64 编码的字符串img1.src = imgUrl;img2.src = signatureimgSrc;// 设置 canvas 的宽度和高度// 这里假设我们将图像水平排列,因此宽度是两幅图宽度之和,高度取最大值canvas.width = img1.width + img2.width;canvas.height = Math.max(img1.height, img2.height);// 绘制第一张图像ctx.drawImage(img1, 0, 0);// 绘制第二张图像,放置在第一张图像的右边ctx.drawImage(img2, 300, 500);// 将合并后的图像导出为 Base64 编码的字符串this.mergedImage = canvas.toDataURL('image/png');},

调用合并图片方法:

javascript">   //点击提交 进行合并图片 保存签名面板内容submit(){this.mergeimg(this.imgUrl,this.signatureimgSrcScale)},

六、效果测试

在这里插入图片描述

七、完整源码

javascript"><template><div class="page"><div><h3>原文档</h3><h3>-----------------------</h3><img :src="imgUrl"></div><div class="sign-box" style="width:300px;height:200px;padding: 10px; margin:10px;background-color: rgb(221 216 216);"><p><span style="color: #f00;">*</span>签名版<span style="color: #f00;">*</span></p><div><canvas id="signCanvas"/></div><button type="default" @click="clear()">清除</button><button type="default" @click="review()">游览</button><button aria-placeholder="添加签名到文件" type="default" @click="submit()">提交</button></div><div><h3>签名</h3><img :src="signatureimgSrcScale"></div> <div><h3>签名后的文档</h3><h3>-----------------------</h3><img :src="mergedImage"></div></div>
</template><script>
import SignaturePad from 'signature_pad'
import html2canvas from 'html2canvas'
import pdf from 'vue-pdf'export default {components: {pdf},data() {return {imgUrl: '../../static/file.png',signatureimgSrc: null,htmlimgUrl: null,signatureExample: null,mergedImage: null,signatureimgSrcScale: null}},mounted() {const canvas = document.getElementById('signCanvas')this.signatureExample = new SignaturePad(canvas, { penColor: 'rgb(0, 0, 0)' })  //penColor   笔的颜色this.adjustSignatureImgPos()},created() {},methods: {//校正签名位置偏移adjustSignatureImgPos() {const canvas = document.getElementById('signCanvas')const ratio = Math.max(window.devicePixelRatio || 1, 1) // 清除画布canvas.width = canvas.offsetWidth * ratiocanvas.height = canvas.offsetHeight * ratiocanvas.getContext('2d').scale(ratio, ratio)},//html页面内容转为base64html2base64(){html2canvas(document.querySelector("#capture")).then(canvas => {this.htmlimgUrl = canvas.toDataURL("image/png"); // 将canvas转换成img的src流});},//合并图片mergeimg(imgUrl,signatureimgSrc){// 创建一个 canvas 元素const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');// 创建两个图像对象const img1 = new Image();const img2 = new Image();// 设置图像的 src 属性为 Base64 编码的字符串img1.src = imgUrl;img2.src = signatureimgSrc;// 等待两张图像都加载完毕// await Promise.all([this.loadImage(img1), this.loadImage(img2)]);// 设置 canvas 的宽度和高度// 这里假设我们将图像水平排列,因此宽度是两幅图宽度之和,高度取最大值canvas.width = img1.width + img2.width;canvas.height = Math.max(img1.height, img2.height);// 绘制第一张图像ctx.drawImage(img1, 0, 0);// 绘制第二张图像,放置在第一张图像的右边ctx.drawImage(img2, 300, 500);// 将合并后的图像导出为 Base64 编码的字符串this.mergedImage = canvas.toDataURL('image/png');},loadImage(img) {return new Promise((resolve, reject) => {img.onload = resolve;img.onerror = reject;});},//点击清除按钮 清除签名面板内容        clear(){//清除签名面板的方法this.signatureExample.clear()},async review(){this.signatureimgSrc =this.signatureExample.toDataURL('image/png')this.signatureimgSrcScale =await this.resizeImage(this.signatureExample.toDataURL('image/png'))console.log("======== this.signatureimgSrc==========", this.signatureimgSrc)},//点击提交 进行合并图片 保存签名面板内容submit(){this.mergeimg(this.imgUrl,this.signatureimgSrcScale)},// 绘制的canvas 进行缩放并转为base64resizeImage(src) {return new Promise((resolve) => {const img = new Image()img.src = srcimg.onload = () => {const originalWidth = img.widthconst originalHeight = img.heightconst scaleFactor = 0.5 // 缩放的倍数const resizedWidth = originalWidth * scaleFactorconst resizedHeight = originalHeight * scaleFactorconst canvas = document.createElement('canvas')canvas.width = resizedWidthcanvas.height = resizedHeightconst ctx = canvas.getContext('2d')ctx.drawImage(img, 0, 0, resizedWidth, resizedHeight)const base64 = canvas.toDataURL('image/png')resolve(base64)}})},}
}
</script>
<style>
.page{display: flex;flex-direction: row;margin: 10px;text-align: center;background: #fff;padding: 10px;
}
</style>

上述代码只是平常练习使用,如需使用在正式项目中,请自行修改完善!!!

在这里插入图片描述


人生从来没有真正的绝境。只要一个人的心中还怀着一粒信念的种子,那么总有一天,他就能走出困境,让生命重新开花结果。



http://www.ppmy.cn/ops/145321.html

相关文章

Scala课堂小结

(一)数组&#xff1a; 1.不可变数组 2.创建数组

路由器转发数据报的封装过程

✍作者&#xff1a;柒烨带你飞 &#x1f4aa;格言&#xff1a;生活的情况越艰难&#xff0c;我越感到自己更坚强&#xff1b;我这个人走得很慢&#xff0c;但我从不后退。 &#x1f4dc;系列专栏&#xff1a;网路安全入门系列 目录 路由器转发数据的封装过程 路由器转发数据的封…

游戏引擎学习第61天

回顾并计划接下来的事情 我们现在的目标是通过创建一个占位符版本的游戏来展示我们所做的工作。这个版本的游戏包含了许多基本要素&#xff0c;目的是快速构建一些东西&#xff0c;进行测试&#xff0c;并观察代码结构的形成。这些代码的实施是为了理解系统如何工作&#xff0…

朗速ERP FileUploadApi.ashx 文件上传致RCE漏洞复现

0x01 产品简介 郎速ERP是一款功能强大的企业资源计划(ERP)软件,专为中小企业量身打造,旨在帮助企业优化管理流程、提升运营效率。不仅适用于制造业,还广泛适用于零售、物流、服务等多个行业。例如,在制造业中,通过生产计划、物料需求计划等功能,提升生产效率和降低生产…

网络安全研究中的网络攻击

网络安全研究中的网络攻击 在网络安全研究中,多种网络攻击场景可用于测试系统的安全性,以下是一些常见的网络攻击场景、模拟方法、相关软件及其使用示例: 分布式拒绝服务(DDoS)攻击 模拟方法:利用工具向目标系统发送大量的请求流量,耗尽其网络带宽、系统资源(如 CPU、…

20_HTML5 SSE --[HTML5 API 学习之旅]

HTML5 Server-Sent Events (SSE) 是一种技术&#xff0c;它允许服务器向浏览器推送更新。与传统的轮询不同&#xff0c;SSE提供了真正的单向实时通信通道&#xff1a;服务器可以主动发送数据到客户端&#xff0c;而不需要客户端发起请求。这对于实现实时更新的应用非常有用&…

DevOps实战:用Kubernetes和Argo打造自动化CI/CD流程(2)

DevOps实战&#xff1a;用Kubernetes和Argo打造自动化CI/CD流程&#xff08;2&#xff09; 背景 架构图 正片开始之前&#xff0c;请一定先熟悉上面的架构图&#xff0c;跟着我的步骤&#xff0c;一步一步执行成功&#xff0c;相信后续根据自己特定的需求定制CI/CD。 需求 …

User Script Sandboxing作用 及 在iOS项目中获取GitCommitHash

User Script Sandboxing 设置为 NO 。这个设置控制了 Xcode 脚本的沙盒限制&#xff0c;默认情况下&#xff0c;Xcode 会将脚本放入沙盒环境中&#xff0c;限制其访问文件系统的权限&#xff0c;尤其是对某些目录&#xff08;例如项目文件夹之外的文件&#xff09;进行修改时&a…