vue实现电子签名、图片合成、及预览功能

业务功能:电子签名、图片合成、及预览功能

业务背景:需求说想要实现一个电子签名,然后需要提供一个预览的功能,可以查看签完名之后的完整效果。

需求探讨:后端大佬跟我说,文档我返回给你一个PDF的oss链接,然后你直接展示,你前端签完名之后给我一个base64的字符串就可以了,我回复ojbk(草率的一批)。

等我转过身,调研一下技术实现发现不对,我大前端需要做一个预览的功能啊,它需要将多张图片合成一张图片,你给我一个oss链接,我怎么转base64。带着这个想法,我跟我们的后端大佬探讨了一下,

最终确定方案是这样:

1.文档的样式由Css+Html去画

2.电子签名的模板转成base64给后端保持不变

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

根据以上,作为一名码农,我翻阅了,github,npm 找到了符合本次功能的插件。

插件:

javascript 复制代码
signature_pad 签名板  链接: https://www.npmjs.com/package/signature_pad
merge-images  合并图像  链接:  https://www.npmjs.com/package/merge-images
html2canvas   html转cavas   链接:https://www.npmjs.com/package/html2canvas

先放效果图:

文档的css+html的样式,我就不献丑了哈,大家按自己的理解来。

电子签名的画板

  • html中创建一个id为signCanvas的canvas元素
javascript 复制代码
<section>
    <div class="sign-box">
      <p><span style="color: #f00;">*</span>{{ $t('本人签名') }}</p>
      <el-button type="default" @click="clear(1)">{{ $t('清空') }}</el-button>
    </div>
    <canvas id="signCanvas" style="width:100%;height:300px;" />
</section>
  • 初始化 SignaturePad
javascript 复制代码
mounted(){
   const canvas = document.getElementById('signCanvas')
   this.signatureExample = new SignaturePad(canvas, { penColor: 'rgb(0, 0, 0)' })  //penColor   笔的颜色   
}

然后我就尝试了一下,发现我鼠标所在的位置跟落笔产生了偏移

然后翻阅文档发现,是需要调用一下这个 resizeCanvas 这个方法

javascript 复制代码
mounted(){
   const canvas = document.getElementById('signCanvas')
   this.signatureExample = new SignaturePad(canvas, { penColor: 'rgb(0, 0, 0)' })  //penColor   笔的颜色   
   this.resizeCanvas()
}

resizeCanvas() {
  const canvas = document.getElementById('signCanvas')
  const ratio = Math.max(window.devicePixelRatio || 1, 1) // 清除画布
  canvas.width = canvas.offsetWidth * ratio
  canvas.height = canvas.offsetHeight * ratio
  canvas.getContext('2d').scale(ratio, ratio)
  this.signatureExample.clear()
},

调用了一下,果然有用。

再加一个清除的方法,官方有提供,直接调用即可

javascript 复制代码
this.signatureExample.clear()

canvas 转base64

javascript 复制代码
this.signatureExample.toDataURL('image/png')    //得到了就是base64的   data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfgAAAL2CAYAAA......

html转cavas

  • 我们需要把html编写的文档转成base64

这个我们用html2canvas 这个插件就可以了

javascript 复制代码
const element = document.querySelector('.html_body') // 需要导出的页面    哪个元素需要转成cavas  就获取它
const htmlCanvas = await html2canvas(element, {
allowTaint: true,
useCORS: true
})
this.imgSrc = htmlCanvas.toDataURL('image/png')    //得到base64

合成图片

  • 接下来我们需要将html文档和电子签名模板,合成一张图片
javascript 复制代码
import mergeImages from 'merge-images'
/* x 、y 是图片在合成图片上的位置(可自行调整)  */
const mergeImagesList = [
    { src: this.imgSrc, x: 0, y: 0 },   //html 转成的base64
    { src: this.signatureExample.toDataURL('image/png'), x: 370, y: 440 }    //  电子签名的 base64   
]
mergeImages(mergeImagesList).then(b64 => {
    this.previewSrc = b64     //返回base64   可直接用于展示
})

这个时候我们看预览的结果发现,电子签名的字好大啊,这是跟我们canvas元素的大小是有关系的,如果我们改变了这个元素的大小,用户签名的时候就会体验感很差,这肯定不符合我们的预期,所以我们要把生成的电子签名等比例缩小。

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

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

javascript 复制代码
// 绘制的canvas 进行缩放并转为base64
    resizeImage(src) {
      return new Promise((resolve) => {
        const img = new Image()
        img.src = src
        img.onload = () => {
          const originalWidth = img.width
          const originalHeight = img.height
          const scaleFactor = 0.3 // 缩放的倍数
          const resizedWidth = originalWidth * scaleFactor
          const resizedHeight = originalHeight * scaleFactor
          const canvas = document.createElement('canvas')
          canvas.width = resizedWidth
          canvas.height = resizedHeight
          const ctx = canvas.getContext('2d')
          ctx.drawImage(img, 0, 0, resizedWidth, resizedHeight)
          const base64 = canvas.toDataURL('image/png')
          resolve(base64)
        }
      })
    },

然后我们重新改下合成图片的方法

javascript 复制代码
  import mergeImages from 'merge-images'
const imgStr = await this.resizeImage(this.signatureExample.toDataURL('image/png'))
const mergeImagesList = [
    { src: this.imgSrc, x: 0, y: 0 },   //html 转成的base64
    { src: imgStr, x: 370, y: 440 }    //  电子签名的 base64   
]
mergeImages(mergeImagesList).then(b64 => {
    this.previewSrc = b64     //返回base64   可直接用于展示
})

ok,没问题了

还有一点需要注意的是,后端是不需要data:image/png;base64,所以还我们需要对这个字符串做个处理

javascript 复制代码
// 获取到image的base64 可以把这个传到后台解析成图片
// imgStr = data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfgAAAL2CAYAAA......
// 去掉data:image/png;base64,我们只要后面的部分iVBORw0KGgoAAAANSUhEUgAAAfgAAAL2CAYAAA......
const subStr = (str) => {
    return str.substring(22, str.length)
}
subStr(this.signatureExample.toDataURL('image/png'))   //返回的就可以直接传给后端啦

总结

本文介绍了电子签名、图片合成、及预览功能,大体的整块逻辑及代码已提供,细节方面需要大家,自行调试哈。

相关推荐
前端不太难14 小时前
没有文档模型,HarmonyOS PC 应用会发生什么?
华为·状态模式·harmonyos
GatiArt雷16 小时前
Libvio.link网站反爬机制深度剖析与合规爬虫策略研究
状态模式
Go_Zezhou16 小时前
render快速部署网站和常见问题解决
运维·服务器·开发语言·python·github·状态模式
共享家95271 天前
搭建 AI 聊天机器人:”我的人生我做主“
前端·javascript·css·python·pycharm·html·状态模式
We1ky1 天前
从零到一:我的javascript记忆翻转卡牌游戏诞生记
状态模式
Elieal2 天前
Spring MVC 全局异常处理实战
spring·mvc·状态模式
Elieal2 天前
统一 JSON 格式,JacksonObjectMapper 定制 Spring Boot JSON 转换规则
spring boot·json·状态模式
前端不太难2 天前
HarmonyOS PC 应用,先做文档模型
华为·状态模式·harmonyos
前端不太难2 天前
HarmonyOS 走向 PC,应用模型正在重构
重构·状态模式·harmonyos
进击的小头3 天前
行为型模式:状态模式——嵌入式状态管理的优雅解决方案
c语言·状态模式