前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >产品让开发一个电子签名、这不是伸手就来?

产品让开发一个电子签名、这不是伸手就来?

作者头像
Snine
发布2023-01-07 09:25:31
4660
发布2023-01-07 09:25:31
举报
文章被收录于专栏:前端开发笔录前端开发笔录

我们日常中应该都经常遇到各种电子合同,需要我们去手动签名,往往只需要手动签名,那么是如何实现的呢?你有了解过么,看似很复杂其实非常简单,初级版本我们甚至只需要不到二十行代码即可实现。当然,真实的场景我们需要考虑更多,那么今天的主角依然是canvas,让我们开始吧!

准备工作

首先我们看到这个需求想到的就是鼠标按下的时候,开始画线,移动的过程中持续画这条线即可,所以第一时间我们想到的就是鼠标按下移动事件,所以我们先用mouse事件实现以下,第一步当然是需要在body中创建这个canvas元素了。

代码语言:javascript
复制
<canvas id="cvs"></canvas>

然后获取到这个元素并对其挂载上按下移动抬起的事件

代码语言:javascript
复制
const cvs = document.getElementById('cvs')
cvs.addEventListener('mousedown', (e) => {})
cvs.addEventListener('mousemove', (e) => {})
cvs.addEventListener('mouseup', (e) => {})

很通用的场景,我们需要在鼠标按下后才开始执行,所以我们定义一个变量,用于记录鼠标是否按下,在down的时候打开,up抬起鼠标的时候关闭,如果不是按下状态,那么我们移动中什么也不做

代码语言:javascript
复制
const cvs = document.getElementById('cvs')
let isDownin = false
cvs.addEventListener('mousedown', (e) => {
    isDownin = true
})
cvs.addEventListener('mousemove', (e) => {
    if(!isDownin) return
})
cvs.addEventListener('mouseup', (e) => {
    isDownin = false
})

好了,准备工作已经完成,我们开始绘制

开始绘制

要绘制的思路很简单,当我们按下鼠标的时候,开始画线,将坐标移动到当前点击点,在移动过程中就会产生非常多的点,将这些点连成线不就可以了么,我们首先需要用到moveTo将坐标移到我们鼠标点下的点,然后在移动过程中使用lineTo将这些点连成线,最后使用stroke绘制出来就行,是不是很简单,我们看看具体代码。

代码语言:javascript
复制
const cvs = document.getElementById('cvs')
const ctx = cvs.getContext('2d')
let isDownin = false

cvs.addEventListener('mousedown', (e) => {
    isDownin = true
    ctx.moveTo(e.pageX, e.pageY)
})
cvs.addEventListener('mousemove', (e) => {
    if(!isDownin) return
    ctx.lineTo(e.pageX, e.pageY)
    ctx.stroke()
})
cvs.addEventListener('mouseup', (e) => {
    isDownin = false
})

就十五行代码就完成了一个看似很牛的功能,是不是很简单了,明白思路了么,当然这个是非常基础的版本,我们先来看看效果:

001.png
001.png

效果出来了,好像还不错,但是我们似乎不能自定义更多的东西,例如我不想要白纸黑字,例如我想要我笔粗一点这该怎么办呢?

自定义样式

我们想要自己定义笔的颜色,想要自己定义笔的宽度,可以怎么做呢,我们直接抽离一个方法吧,后续需要什么颜色,什么宽度自己改好了

代码语言:javascript
复制
function drawLine(x,y){
    ctx.beginPath();
    ctx.lineWidth = 5;
    ctx.strokeStyle = '#fff'; 
    ctx.moveTo(lastX, lastY);
    ctx.lineTo(x, y);
    ctx.stroke();
    lastX = x;
    lastY = y;
}

这里我们可以给lineWidth设置宽度代表了笔的宽度,给strokeStyle设置颜色,代表绘制线的时候的颜色,但是我们看到了新增了lastXlastY,这是因为我们抽离出来单独方法了,每次绘制需要先moveTo移动到新的点去才能继续绘制,稍微有点不同,然后我们在mousemove的过程中传坐标过来即可,当然如果还想做其他的美化,比如lineJoinlineCap等其他属性,设置线的交汇处是否有圆角边等等这些操作可以自己去尝试选择,好了我们已经可以自定义绘制一个我们喜欢的样式了,看看效果。

002.png
002.png

貌似有点东西了,但是如果你是产品,我相信你这时会有这有一个疑问,我名字这么复杂,手写本来就不好写,我要是写错了咋办,重头开始?还是让我能回到上一笔,作为一个有经验的程序员,我会读产品说:不好意思、这个需求做不了、你找别人吧!

但是看看钱包,当然还是选择原谅她了。

实现书写回退,清空功能

现在我们写到一半了,需要清空,那当然easy了,一个按钮,点击之后我们清空即可,canvas的清空还不是简简单单,从(0,0)左上角到最右边,进行clearRect即可实现,这不是轻轻松松么。

代码语言:javascript
复制
ctx.clearRect(0, 0, width, height)

那么如何实现回退呢,要想实现后退,那么用户每画完一笔我们得保留他此次的轨迹,下次要是回来我们需要把数据放回去,如何实现呢?

通过 getImageData() 复制画布上指定矩形的像素数据,然后通过 putImageData() 将图像数据放回画布

这样一看,我们创建一个cacheData用户记录记录,每当我们按下鼠标的时候说明上次已经结束了,我们通过getImageData拿到之前的所有数据,push到cacheData,那么用户点击回退的时候,我们只需要拿到最后一项即可,然后通过putImageData放回去即可,这不是轻轻松松又实现了么?

代码语言:javascript
复制
ctx.getImageData(0, 0, width, height);
ctx.putImageData(cacheData.pop(), 0, 0);
dianziqian.gif
dianziqian.gif

好了我们已经实现了回退清空功能,产品又发话了,用户签完字得截图保存作为凭证啊,不然怎么知道用户签字了呢,也对,那我们还得想办法把用户签的字保存为图片,如何实现呢?

保存签名为图片

作为canvas其实已经提供了两种方法来进行图片导出

  1. toDataURL,这个方法是同步的,转为base64,然后我们就可以导出了
  2. toBlob可以将其转为blob流文件,这个方法是异步的,

在日常中我们更推荐toBlob,有看到别人说过如果toBlob可以早点出现,就完全没必要有toDataURL这个方法,一方面第一个api容易拼写错误,另一方面,这是一个同步方法,如果过大,这个是会进行堵塞的,所以以后我们优先选择toBlob,即可,使用非常简单,转为blob流文件,在回调函数中拿到他,然后我们创建一个a标签,然后通过URL.createObjectURL可以获取当前文件的一个内存URL,然后就可以下载了。

代码语言:javascript
复制
cvs.toBlob((blob) => {
    const a = document.createElement('a');
    document.body.append(a);
    a.download = `签名.png`;
    a.href = URL.createObjectURL(blob);
    a.click();
    a.remove();
  });

好了,我们即可以让用户自己下载,也可以传到服务端保存,那么我们这个生成图片的功能就此完成了。

看似万事俱备之前东风了,按照以往的惯例,我们可以一把梭,然后上线了,但是我相信,上线不久产品会再次找到你,询问为什么手机上用不了,此时你应该恍然大悟,我们的mouse事件只支持pc啊,所以我们此时应该兼容手机端了。

兼容手机端了

由于码上掘金并不支持移动端,我们就不写示例代码了,只讲解思路即可,因为也非常简单,我们知道mouse事件对应的移动端是touch事件,所以,在使用前,我们应该先判断环境,当判断环境是移动端的情况下,我们就使用mouse对应的touchstart/touchmove/touchend/touchcancel等事件即可,同时获取X,Y坐标的位置相对也改变一下,比如移动端的X坐标就是e.changedTouches[0].clientX,此时我们就也支持移动端了,好了一个相对完整的电子签功能已经实现了,上线,下面可以找产品要鸡腿了。

在线体验

完整的代码在码上掘金大家可以自行体验

使用canvas开发一个完整的电子签

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023 年 01 月,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 准备工作
  • 开始绘制
  • 自定义样式
  • 实现书写回退,清空功能
  • 保存签名为图片
  • 兼容手机端了
  • 在线体验
相关产品与服务
腾讯电子签
弹指间,放心签。腾讯电子签(E-Sign Service)致力为企业及个人提供极简且高效的电子合同管理工具。您只需要一部手机即可完成合同签约及常见的合同管理操作;电子签将对签约全程进行区块链记录,为您的业务与生活保驾护航。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档