前言
古茗目前已经有近万家门店了,为了对门店做规范管理,会进行巡店且输出巡店报告,此时就需要有一个老板签名的功能,证明老板认可且了解当前结果。由于我们巡店用到的是钉钉小程序,所以下面将会为大家展示如何在小程序中实现一个签名板功能。
设计实现
为了实现签名功能,需要用到 canvas,我们翻阅钉钉 api 文档,发现支持Canvas
组件,very nice,下面开始实现。(由于我们内部使用 taro 框架,以下代码均为 taro + react,我们设计稿均为 750,所以样式中数值均是实际的2倍)
创建canvas
我们先在页面中创建一个canvas画布
1 | jsx复制代码// SignaturePad.jsx |
此时会发生一个神奇的现象,明明设置了 width=343 和 height=180,怎么还是钉钉默认的 300x225 ?别急,我们往下走。
调整画布
为了得到正确的展示大小,我们可以通过设置样式实现
1 | jsx复制代码// SignaturePad.less |
确实是起效了,那么设置width
和height
属性有什么用呢,我们看下钉钉文档,可以发现这两个属性可以用来控制绘画精细度,解决在高dpr的情况下造成的绘画模糊问题。
这里还需要注意,宽高属性需要和css中宽高属性保持相同比例,否则绘画会出现扭曲情况
初始化
画布创建完成了,接下来需要实现画笔功能,这时候就需要结合CanvasContext
绘图上下文对象预设画笔属性以及后续绘图需要用到的坐标轴
1 | jsx复制代码// SignaturePad.jsx |
绘画
所有准备工作完成,然后就是如何实现绘画功能了。想要实现绘画,要对 canvas 有所了解,canvas 元素默认被网格所覆盖。通常来说网格中的一个单元相当于 canvas 元素中的一像素。栅格的起点为左上角,坐标为 (0,0) 。所有元素的位置都相对于原点来定位。所以图中蓝色方形左上角的坐标为距离左边(X 轴)x 像素,距离上边(Y 轴)y 像素,坐标为 (x, y)
Canvas相关属性
了解了基础知识,我们就基本知道如何实现了。通过onTouchStart
确定画笔开始坐标,onTouchMove
获取用户在canvas内的绘画路径,将路径上所有的点都填充上颜色。
1 | jsx复制代码// 是否绘画过 |
添加操作
到这里,基础的绘画已经完成了,但是我们是需要将生成的签名保存到服务端的,所以还需要有一个确定操作。
1 | jsx复制代码const createImg = async () => { |
有了确定操作,假如用户签错名字了想要重写,还需要一个清除操作。
1 | jsx复制代码let canvasw = 0; |
到这里,一个基础的签名板已经完成了,但是还有一些可以优化的地方,下面我们将继续对它进行一些优化。
优化
撤回
清空虽然能解决用户写错的问题,但是只撤回上一笔对用户体验来说是更好的。我们可以创建一个history
用于记录用户每一次绘画,然后通过getImageData
获取canvas区域隐含的像素数据,将其push()
到history
中,在触发撤回操作时,将最新一条数据pop()
同时清空画布,再通过putImageData
将history
最后一条像素数据绘制到画布上,这样就能实现撤回效果。
1 | jsx复制代码const history = useRef([]); |
横屏
竖屏时签字区域相对较小,只要将其切到横屏那么体验将会好非常多了。查阅钉钉文档,发现并没有提供小程序切换横竖屏的api,那么只能我们自己做一个横屏效果了。我们可以通过rotate
和translate
样式,将签名版横置,再对其调整宽高。
1 | jsx复制代码// SignaturePad.jsx |
然后,我们就可以看到如图效果,签名版是横置了,但是这个签名功能明显不对了。通过打印onTouchMove
的event
,我们发现x,y依然是(0, 0)
,因为屏幕的xy轴不会变,但是我们旋转了整个签名版,所以展示出的canvas的xy轴是跟随着变形了,导致了上图情况。
既然canvas旋转会导致xy轴变化,那么我们可以换个角度,只改变canvas的宽高,将标题按钮区域进行transform
是不是就可以了
1 | jsx复制代码// SignaturePad.jsx |
ok,可以看到,签名功能又正常了。但是,在我们点击清空的时候发现清空也坏了,这是因为我们调用的clearRect
是清除画布上在该矩形区域内的内容,所以原本在初始化获取的Canvas
宽高在横屏的时候实际上已经发生了变化,只要在横屏时重新获取一次组件宽高即可
1 | jsx复制代码const toggleSize = () => { |
好了,到这里已经能得到一个相对完整的签名版功能了
总结
以上就是签名版的实现,实际上H5的实现也是类似的,只是某些部分会和小程序有所区别。整个签名板的实现基本上就是使用canvas,没有特别复杂的点,但是过程中总会遇到奇奇怪怪的问题,当你一个一个解决之后,你会发现,今天的姿势又能+1,这不就是程序员的快乐吗。感谢阅读。
最后
📚 小茗文章推荐:
关注公众号「Goodme前端团队」,获取更多干货实践,欢迎交流分享~
本文转载自: 掘金