canvas 签名,

  canvas 签名,

  前言

  一般来说,电子签名就是通过技术手段在电子文档上加载电子签名,其作用类似于纸质合同上的手写签名或公章。虽然多年来电子签名的合法性一直受到质疑,但它被广泛应用于企业工作流审批、邀请、文档保存等场景。在最近的项目中,有这样的手写签名和PDF文件生成的需求。

  实现思路

  用canvas实现手写签名的功能,然后把canvas转换成图片,粘贴在签名位置;利用html2canvas插件把整个需要生成文档的dom区域变成一个大图;用JsPDF插件从上面的图片生成PDF文档;文件较多时,要合理选择分页位置。生成签名

  1. 在tsx中定义canvas画布

  Canvas class name={styles。canvas } ref={ canvas DOM } width= 350 height= 150 /注意:画布的宽度和高度必须由inline style定义,因为画布标签有自己默认的宽度和高度300px150px。由它的内联样式定义的宽度和高度是绘制区域(画布)的实际宽度和高度,在其上绘制的图形都是。如果它的宽度和高度是在样式链文件中定义的,那么宽度和高度就是在浏览器中呈现的画布的高度和宽度。如果宽度和高度没有在Canvas中直接定义,或者值不正确,它们将被设置为默认值{width:300px,height:150px}。所以,如果在样式外链文件中设置canvas {width: 200px );高度:200px},但是画布的宽度和高度没有直接在画布上定义,那么你的输出canvas.height值还是150,canvas.width值还是300。即在200200的区域内渲染一张150300的画布,所以画面会被拉伸变形。

  2. 定义签名函数

  const writing=( beginX: number,beginY: number,stopX: number,stopY: number,ctx: any),={ CTX . begin path();//打开新路径CTX . global alpha=1;//设置图片的透明度CTX . line width=3;//设置线宽ctx.strokeStyle= red//设置路径颜色ctx.moveTo为(beginX,beginY);//从坐标点(beginX,beginY)开始绘制ctx.lineTo(stopX,stopY);//定义从(beginX,beginY)到(stopX,stopY)的直线(此方法不会创建直线)CTX . close path();//创建路径CTX . stroke();//实际绘制moveTo()和lineTo()方法定义的路径。默认颜色是黑色。};3. 注册监听事件

  let beginX: number,beginY:number;const canvas:HTMLCanvasElement=canvasdom . current;const CTX=canvas . get context( 2d );ctx.fillStyle= # fffctx.fillRect(0,0,canvas.width,canvas . height);canvas . addevent listener( touch start ,function(event:any){ event . prevent default();//在画布上签名时防止页面滚动。Beginx=event.touches [0]。clientx-this . offset left;beginY=event.touches[0]。pageY-this . offsettop;});canvas . addevent listener( touch move ,(event:any)={ event . prevent default();//在画布上签名时防止页面滚动event=event . touches[0];let stopX=event . clientx-canvas . offset left;let stopY=event . pagey-canvas . offsettop;写(beginX,beginY,stopX,stopY,CTX);beginX=stopX//这一步很关键,起点需要不断更新。否则,绘制光线簇beginY=stopY});注意:

  注册“touchstart”和“touchmove”事件时,需要屏蔽默认事件,否则页面会随着手势上下滑动。移动端的每个触摸事件对象都包含touches,用来描述屏幕上所有手指的列表,获取当前事件对象。我们习惯性地使用event=event.touches[0],但在PC端不需要这么做。OffsetLeft和offsetTop值与父元素无关,与它们上面的定位元素(除position:static以外的所有定位元素,如fixed、relative、absolute绝对元素)有关。如果上层的定位元素都没有position:staice以外的位置,则此偏移是相对于几何体的。有必要澄清移动终端的事件对象的几个属性,

  ClientX/clientY:触摸位置距离当前身体可视区域的x,y坐标;

  PageX/pageY:对于整个页面,从正文左上角开始的触摸位置的x,y坐标,包括scrolled top和scrollLeft的值;

  ScreenX/screenY:触摸位置与显示屏左上方之间的x,y距离。

  所以在得到终点的坐标时,如果当前页面没有滚动条,clientY和pageY差别不大。如果页面很长并且有滚动条,那么必须使用pageY来计算。clientX也一样,但是移动端通常横向滚动的场景不多,所以可以用ClientX来计算。

  在签约(touchmove)的过程中,我们需要不断更新起始位置,否则就会这样。

  其实这个原理和微积分很像。本质上,一条线段是由无数条小线段组成的。从宏观的角度来看,线段可以看作是首尾相连的长度非常小的小线段。所以我一直认为编程到最后是对一个人数学能力的考验,数学可以看交集和并集,逻辑思维,算法等。最后,生成的签名如下:

  生成PDF文档

  2 html2Canvas是一个将html代码转换成Canvas的插件,所以需要在需要打印的内容区域周围包装一个div来获得这个dom节点。

  2 HTMLcanvas (DOM,{allowtain: true,width: dom.offsetwidth,//设置获取的画布宽度高度:dom.offsetHeight,//设置获取的画布高度x: 0,//页面水平方向滚动距离y: 0,//页面垂直方向滚动距离})注意:这里需要设置宽度和高度以及x,y,否则页面内容只有一页时不会有问题,但是如果页面很多,就会出现生成的图片只有一小部分有问题出在这个配置参数上。如果未设置宽度和高度,则默认情况下,仅获取当前视窗的内容,当前视窗之外的其他内容将被丢弃。

  设置打印参数:

  const print=()={ let DOM:html element=pdf DOM . current;2 HTMLcanvas (DOM,{allowtain: true,width: dom.offsetwidth,//设置获取的画布宽度高度:dom.offsetHeight,//设置获取的画布高度x: 0,//页面水平方向滚动距离y: 0,//页面垂直方向滚动距离})。然后((canvas:html canvas element)={ let canvas width=canvas . width;设canvasHeight=canvas.heightlet page height=(canvas width/592.28)* 841.89;//A4 pdf一页能显示的画布高度let imgWidth=595.28//设置图片的宽度等于A4纸的宽度let img eight=(592.28/画布宽度)*画布高度;//按比例换算成A4纸的高度,让totalHeight=imgHeight//要打印的图片的总高度,初始状态和图片的高度相等。let pagedata=canvas . toda taurl( image/png ,1.0);设PDF=new JsPDF(p , pt , a4 ,true);if(total height page height){//pdf . addimage(pageData, JPEG ,0,0,imgWidth,img height);//从顶部打印} else { let top=0;//打印初始区域while(total height 0){ pdf . addimage(pagedata, JPEG ,0,top,imgwidth,img eight);//从图片顶部到顶部位置打印total height-=page height;top-=841.89;if(total height 0){ pdf . add page();} } } pdf . save( test . pdf );});};选择分页位置

  按照上面的步骤,生成一个PDF文档,但是当PDF中的页面很多的时候,就会出现这样的问题。

  如你所见,这一段的分页符被剪掉了。这显然不是我们希望看到的效果。怎么才能解决这个问题?

  当PDF文档中的页数很小时

  开发测试时可以提前在要分页的地方插入一个填充,也就是提前预留分页位置。

  PDF有更多的页面。

  在这种情况下,作者试图遍历要打印的dom节点的子节点,并累积每个页面上可以打印的dom节点的高度。如果超过页面所能承受的最大高度,最后一个节点将被填充,打印后将恢复样式。由于这种方法需要计算每个dom节点的高度,因此消耗了大量的性能,同时也要求页面中dom元素的粒度要精细。否则一页会有很大的空白,根本模拟不出word生成pdf的效果,就不讨论了。

  关于Html5实现基于canvas的电子签名并生成PDF文档的这篇文章到此为止。有关canvas电子签名的更多信息,请搜索以前的文章或继续浏览下面的相关文章。希望你以后能支持我!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: