前言 电子署名平常来说就是通过技能本领实现在电子文档上加载电子形式的署名,其作用类似于纸质合同上的手写署名或加盖的公章。虽然电子署名多年来合法性不停遭到质疑,但其在企业工作流审批、请柬、票据保全等场景应用广泛,最近的项目中就有如许一个手写署名并生成PDF文件的需求。 实现思绪
生成署名 1. 在tsx中定义canvas画布 [code] <canvas className={styles.canvas} ref={canvasDom} width="350" height="150" />[/code][code]注意[/code]:Canvas的宽高必须要使用内联样式定义,这是由于Canvas标签有本身的默认宽高300px×150px。它内联样式定义的width和height是绘画区域(画布)实际宽度和高度,绘制的图形都是在这个上面。假如在style外链文件中定义其width和height,那么这个width和height是Canvas在浏览器中被渲染的高度和宽度。假如Canvas中没有直接定义width和height没或值不准确,就会被设置成默认值{width:300px,height:150px}。所以,假如你在style中外链文件中设置了canvas {width: 200px; height: 200px;},却没有直接在canvas上定义画布宽高,那么此时你输出canvas.height 值依旧为150,canvas.width值依旧为300。也就是一块150×300的画布在200×200的区域渲染,因而图片会出现拉伸、变形等现象。 2. 定义署名函数 [code] const writing = ( beginX: number, beginY: number, stopX: number, stopY: number, ctx: any, ) => { ctx.beginPath(); // 开启一条新路径 ctx.globalAlpha = 1; // 设置图片的透明度 ctx.lineWidth = 3; // 设置线宽 ctx.strokeStyle = 'red'; // 设置路径颜色 ctx.moveTo(beginX, beginY); // 从(beginX, beginY)这个坐标点开始绘图 ctx.lineTo(stopX, stopY); // 定义从(beginX, beginY)到(stopX, stopY)的线条(该方法不会创建线条) ctx.closePath(); // 创建该条路径 ctx.stroke(); // 实际地绘制出通过 moveTo() 和 lineTo() 方法定义的路径。默认颜色是黑色。 };[/code]3. 注册监听变乱 [code] let beginX: number, beginY: number; const canvas: HTMLCanvasElement = canvasDom.current; const ctx = canvas.getContext('2d'); ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, canvas.width, canvas.height); canvas.addEventListener('touchstart', function(event: any) { event.preventDefault(); // 阻止在canvas画布上署名的时间页面跟着滚动 beginX = event.touches[0].clientX - this.offsetLeft; beginY = event.touches[0].pageY - this.offsetTop; }); canvas.addEventListener('touchmove', (event: any) => { event.preventDefault(); // 阻止在canvas画布上署名的时间页面跟着滚动 event = event.touches[0]; let stopX = event.clientX - canvas.offsetLeft; let stopY = event.pageY - canvas.offsetTop; writing(beginX, beginY, stopX, stopY, ctx); beginX = stopX; // 这一步很关键,需要不停更新起点,否则画出来的是射线簇 beginY = stopY; });[/code][code]注意[/code]:
需要理清移动端变乱对象的几个属性,⏬ clientX/clientY: 触摸位置隔断当前body可视区域的x,y坐标; 在署名(touchmove)这个动作过程中,我们需要不停的更新起点位置,否则画出来是如许🔽
其实这个原理和微积分很相似,线段本质上就是由无穷多个小线段构成,宏观一点来看可以把线段当成一个个长度很小的小线段首尾相连构成。所以我不停觉得编程编到最后就是考验一个人的数学本领,交并集、逻辑头脑、算法等都能看到数学的身影。最后生成署名如下: 生成PDF文档 html2canvas是一款将HTML代码转换成Canvas的插件,因此需要用一个div包裹住需要打印的内容区域,得到这个dom节点。 [code] html2Canvas(dom, { allowTaint: true, width: dom.offsetWidth, //设置获取到的canvas宽度 height: dom.offsetHeight, //设置获取到的canvas高度 x: 0, //页面在程度方向滚动的隔断 y: 0, //页面在垂直方向滚动的隔断 }) [/code][code]注意[/code]:此处需要设置width和height及x,y,否则当页面内容只有一页的时间没有题目,但是若页面内容有很多页的时间,就会出现生成的图片只有一小部门有内容的现象。题目就出现在这个配置参数上,若没有设置宽高,则默认只取当前视口的内容,丢弃掉其他超出当前视口的内容。 选择分页位置 按照上述步骤生成了一份PDF文档,但是当PDF页数有很多的时间,会有如许的题目⏬
可以看到,分页的时间从这段文字这里懒腰截断了。这显然不是我们想要看到的效果,怎样办理这个题目呢?🤔 PDF文档页数较少的情况 可以在开发测试的时间预先在将要分页的地方插入一个padding,就是提前预留分页位置 PDF文档页数较多 对于这种情况,笔者尝试遍历要打印的dom节点的子节点,将每一页所能打印的dom节点高度累加,若超过了页面所能承载的最大高度,则将最后一个节点增长padding,打印完毕将样式还原。这种方法由于要盘算每个dom节点的高度,非常耗性能,也要求页面dom元素的颗粒度较细,否则会出现一个页面有大块空白,完全无法模仿出word生成pdf的那种效果,所以就不展开讨论了。 到此这篇关于Html5基于canvas实现电子署名并生成PDF文档的文章就介绍到这了,更多相关canvas电子署名内容请搜索脚本之家从前的文章或继承浏览下面的相关文章,盼望各人以后多多支持脚本之家! 来源:https://www.jb51.net/html5/755406.html 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
|手机版|小黑屋|梦想之都-俊月星空
( 粤ICP备18056059号 )|网站地图
GMT+8, 2025-7-2 02:11 , Processed in 0.030647 second(s), 18 queries .
Powered by Mxzdjyxk! X3.5
© 2001-2025 Discuz! Team.