前端基于React实现的PDF在线预览签名导出个人文章

最近做了一个简单版的电子合同,现在把这个项目中的一小部分功能,做了一个demo版本的PDF在线预览-签名-下载。

这个demo主要涉及三个环节,也就是PDF预览-签名-导出。

我遇到的,涉及pdfjs的坑有这么几个:

之前的项目有个功能点,签名状态可以保留。即合同需要两个人签署,如果一个人在移动端签名,放到PC端签名的位置会出现偏差;同理,PC端的签名放到移动端去看也会有差异。

分析问题:签名的数据,是会统一放到signPositionList里,上传数据库并进行保存。

//大概的签名数据信息interfaceISignPosition{id:string;x:number;//相对pdf渲染的偏移值xy:number;//偏移值yw:number;//签名宽h:number;//签名高signSrc:string;//签名图片isSelect:boolean;innerPdfIndex:number}typeSignList=ISignPosition[];上传的时候,会把签名的偏移值进行存储,预览的时候,获取签名的偏移值进行定位预览。

在看下签名偏移值x,y是怎么储存的:

//返回签名相对于pdfcanvas视口的偏移值exportconstgetTouchPosition=(e:any,scale:number)=>{constevent=getEvent(e);consttarget=event.target;constrect=target.getBoundingClientRect();constx=event.pageX-rect.left;consty=event.pageY-rect.top;//scale=canvas容器宽度/pdf渲染出来的canvas真实宽度return{x:x/scale,y:y/scale}}通过分析排查,问题的关键点就在于scale,主要原因是在PC和移动端两种不同环境下,pdfjs所渲染出来的容器宽度不一样,这里贴下当时手里的测试机,在两个环境中,签名的pdf宽高对比:

定位出问题以后,就开始分析解决,最终有了两种解决方案:

通过分析pdfjs源码可以得知,在pdfjs渲染时,除了当时浏览器宽度,其中有根据两个参数来控制的:

devicePixelRatio大家应该不陌生了,随着各种显示器设备的不断升级,这个值也在慢慢不断升级。值1表示经典96DPI(在某些平台上为76DPI)显示,而对于HiDPI/Retina显示屏则期望值为2。在异常低分辨率的显示器中,或更常见的是,当屏幕的像素深度比简单地将96或76DPI的标准分辨率提高一倍时,可能还会返回其他值。

maxCanvasPixels字面意义就是可以渲染的最高像素数,这个值在pdfjs源码里可以进行设置,如下图:

constMAX_CANVAS_PIXELS=_viewer_compatibility.viewerCompatibilityParams.maxCanvasPixels||16777216;classPDFPageView{constructor(options){constcontainer=options.container;constdefaultViewport=options.defaultViewport;this.maxCanvasPixels=options.maxCanvasPixels||MAX_CANVAS_PIXELS;...}如果想让pdfjs保持两端一致的渲染比例,可以对devicePixelRatio和maxCanvasPixels这两个值进行如下赋值:

window.devicePixelRatio=3;constpdfViewer=newpdfjsViewer.PDFViewer({container:containerRef.current,eventBus:eventBusRef.current,linkService,maxCanvasPixels:5242880,l10n:pdfjsViewer.NullL10n,useOnlyCssZoom:USE_ONLY_CSS_ZOOM,textLayerMode:TEXT_LAYER_MODE});这种方法比较hack,简单粗暴,改动最少,但是不同的手机设备预览可能会产生更多的风险。不建议使用。

算出上图中,签名偏移值在PC->H5之间的转换公式:

h5.x=h5.width*(pc.x/pc.width)h5.y=h5.height*(pc.y/pc.height)第一步,保存签名数据时,增加签名相对canvas容器的绝对百分比定位值:

//修改签名的数据信息,增加百分比偏移值interfaceISignPosition{id:string;xPercent:number;//相对canvas真实宽度的百分比位移yPercent:number;//相对canvas真实高度的百分比位移...}constrequestSignList=signList.map((sign)=>{return{...sign,xPercent:sign.x/trueWidth,yPercent:sign.y/trueHeight,}})第二步,在预览时,接口返回签名数据后,从百分比转成绝对值:

constsignList=apiSignList.map((sign)=>{return{...sign,x:trueWidth*xPercent,//真实偏移值/当前比例y:trueHeight*yPercent,}})这里只是贴些伪代码,本文里的这个项目并不涉及到需要h5&pc共同保存签名的功能。

eventBusRef.current.on("pagesloaded",function(){pdfViewerRef.current.currentScaleValue=DEFAULT_SCALE_VALUE;});但是如果你的pdf页数有点多,pdfjs出于性能问题考虑,会进行懒加载,如果这个时候,你想在pdfjs上层增加一个canvas渲染层,就不能监听到该事件就一起给加了,这个时候其实还有很多pdf并没有开始渲染。

pdf在浏览器中,应用canvas的地方有很多,如书写签名,签名交互以及签名的合成计算...

首先回顾一下,这个项目涉及canvas的有三处:

第一个canvas,是pdfjs渲染pdf生成的pdfCanvas,这里也就是pdf本身内容;

第二个canvas,是和pdfCanvas重叠生成的pdfSignCanvas,前边已经说过pdfSignCanvas是出于性能考虑的,主要是在执行签名的生成和交互时,这一层的canvas会频繁进行绘制,如果这个时候只有一层canvas,那么每次在pdfCanvas上开始拖拽签名进行交互时,将会频繁的重新绘制整个pdf的内容,这里的性能开销就非常大了。这一层canvas也是一开始的时候没有加,等到测试的时候,发现低端手机,各种花屏,卡顿,才给加上的。

canvas本身是没什么坑的,也就是api比较多,使用门槛相比其他库有点高...

关于canvas的一些使用技巧:先看一下,签名画板部分signPannelCanvas:

你可以在这个白色面板上进行签名/绘画,点击保存时,在将signPannelCanvas与signCanvas进行合并。以便将签名保存到pdf的画布中进行预览。如果按照传统做法,直接合并的话,那签名的区域会出现很多空白,毕竟你不可能把整个画布签满。

优化方案就是,我在两个canvas将要合并的时候,加了一个裁剪的过程:

整体优化流程:

这个项目的落地页是需要兼容PC和H5的,好在页面设计不是很复杂,没有太多需要特殊兼容的部分。

需要特殊处理的,就是签名画板的部分。因为手机的屏幕尺寸显然不如web宽敞,为了让用户有个较好的签名体验,需要将整个画布进行横向展示。

无论用户有没有开启手机的自动旋转,都要让用户横着手机进行签名。

为了考虑手机的自动旋转,需要加个监听事件,重新设置signPannelCanvas的宽高.

constgetCanvasSize=():Promise=>{returnnewPromise((resolve)=>{setTimeout(()=>{if(window.orientation===90){resolve({width:window.innerWidth,height:window.innerHeight-TITLE_MAP,})}else{resolve({width:window.innerWidth-TITLE_MAP,height:window.innerHeight,})}},500)})}consthandleCanvasSize=async()=>{constsize=awaitgetCanvasSize();updateCanvasSize(size);};useEffect(()=>{//加载签名模板,获取初始化大小handleCanvasSize();window.addEventListener("orientationchange",handleCanvasSize);return()=>{window.removeEventListener("orientationchange",handleCanvasSize);}},[]);最后一点,需要注意的是,移动端在强制横屏后,signPannelCanvas的宽高与手机的宽高是相反的。

所以在保存签名的时候,我们需要在把signPannelCanvas的签名翻转一下,才行。不然直接保存的话,签名也就跟着是反的。

//竖屏状态-翻转图像进行保存constctx=signPannelCanvas.getContext('2d');ctx.clearRect(0,0,width,height);canvas.width=clipSize.h;canvas.height=clipSize.w;constimg=createImage(imgData)img.onload=function(){//反向翻转绘制图片ctx.save();ctx.translate(clipSize.h/2,clipSize.w/2);ctx.rotate(-90*Math.PI/180);ctx.translate(-clipSize.h/2,-clipSize.w/2);ctx.drawImage(img,clipSize.h/2-img.width/2,clipSize.w/2-img.height/2);ctx.restore();//canvas有个重绘的过程,不能直接进行保存setTimeout(async()=>{//翻转后的正确签名constsignImage=canvas.toDataURL('image/png');addSignInCanvas(signImage,canvas.width,canvas.height);})}3.最后一个环节:pdf的导出/下载pdflib-支持原汁原味的pdf下载,这个库很方便,说到html->pdf转换,网上有很多方案,大都是将htmlToCanvas,imgToCanvas,toPdf。总之生成的pdf内部大都是图片,已经不是原汁原味的pdf了,这个库可以让你在原汁原味的pdf上额外添加图片,svg,文字等等...

这里比较折腾的一点是,如何把signCanvas上的图片,准确无误的添加到pdf文件指定的区域中。这里就直接贴代码了。和上面pc->h5的方案思路一致。

想熟悉canvas的同学,可以多了解一下。其中涉及canvas的内容,我上面没有讲太多,比如签名的绘制,交互,拖拽,变形等等...

顺带附下github地址,如果觉得有帮助,可以帮忙点个star,感谢~~

THE END
1.腾讯表格在线签名方法您是否经常遇到需要在线签名的表格,但又不知道如何操作?不用担心!本文将为您详细介绍腾讯表格的在线签名方法,让您轻松解决这个问题。 方法一:使用手写签名 第一步:打开腾讯表格并选择需要签名的单元格。 第二步:点击工具栏上的“插入”选项。 第三步:在弹出的菜单中选择“手写签名”。 https://www.huoban.com/news/post/154753.html
2.如何在线设计签名?手把手教你自己设计签名如何在线设计签名?很多时候我们外出谈生意,最终拍板的时候都需要手动签署合同。还有有的时候我们去银行办理业务都是需要进行签名的。一个好看的签名能够给他人留下更好的印象,故而平时对签名的练习必不可少。这里小编就来给大家分享在线给大家设计签名的办法,这样大家私下对着多多练习就一定可以写出专属于自己的漂亮签名https://cloud.tencent.com/developer/news/978004
3.如何在电子文档上签名(在线手写签字怎么弄)电子合同我们在工作和生活中可能会遇到这样的情况,需要在声明函或其它在线文件中填加自己的手写签名,要怎么操作呢,本文来科普如何在电子文档上签名,在线手写签字怎么弄。 如何在电子文档上签名 现在很多文件签名都要保障有效性,所以可以制作一个「可靠的电子签名」以备不时之需。在法大大只需注册并认证即可生成本人的签名,https://m.fadada.com/notice/detail-20863.html
4.如何发送文档以进行在线签名了解如何使用 Adobe Acrobat 在线“发送以请求签名”服务来让他人对文档或协议进行签名。https://helpx.adobe.com/cn/document-cloud/help/send-for-signature.html
5.如何在线生成电子签名(小程序怎么制作电子版电子签名?)仙剑之家手写电子版电子签名如何实现呢?不需要下载App也不需要PS技能,只需一部手机,今天就教你免费get电子版电子签名新技能。 第一步:打开微信 我们都有微信的对吧,首先拿出手机微信小程序搜索“微签”,点进“微签云” 第二步:登录“微签” 进入小程序后,使用手机验证码登录就可以立即体验。如果是第一次使用的小伙伴,要https://www.0577fl.com/otgame/65174.html
6.在线文档怎么签名字,三种简单方法教你一步步完成签名在线文档已经成为现代生活中不可或缺的一部分。签名是在文件上确认身份或同意其内容的重要步骤。你可能会问:在在线文档中如何添加电子签名或手写签名?在这篇文章中,我们将介绍三种简单的方法来帮助你完成签名,让你的在线文档更具法律效力。 方法一:使用电子签名工具 https://bbs.wps.cn/cms/mFqjULKI.html
7.电子签名如何设计?一款在线电子签名生成器推荐!电子签名如何设计?一款在线电子签名生成器推荐! 无论是工作还是生活中,我们都会在各种各样的文件上面签署自己的名字,只有签名的文件才会生效,有些文件比较特殊,除了需要签名之外还需要按手印。签名自古以来都是很有作用的,随着经济的快速发展,现在很多文件都会采用电子版的格式,这个时候就需要大家提供电子签名。一个好看https://cloud.tencent.cn/developer/news/1167654
8.如何使用电子签名在线签署文档?–支援中心点点签当您收到电子邮件中的签名请求时,您可以轻松使用点点签签署文档。我们提供多种方式来创建您的电子签名,包括签名、签名缩写、图章和公司印鉴。在线签署文档仅需几分钟! 如何创建电子签名签署文档? 点击电子邮件中的签署邀请连结。(如果您已登录点点签,请直接前往「文档」并打开需要签名的任务。) https://support.dottedsign.com/hc/zh-cn/articles/900001647846-%E7%AD%BE%E7%BD%B2%E6%96%87%E4%BB%B6
9.如何用canvas实现在线签名的示例代码html5网页制作在我们在日常生活中,已经有很多场景使用在线签名技术,这篇文章主要介绍了如何用canvas实现在线签名的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 GPT4.0+Midjourney绘画+国内大模型 会员永久免费使用! 【如果你想靠AI翻身,你先需要一个靠谱的工具!】 https://www.jb51.net/html5/624184.html
10.一键logo设计怎么设计自己的签名?个性签名设计在线分享设计个性化的签名是展示出独特个性的绝佳途径之一,无论是用于电子邮件、社交媒体还是文书信函,一个独特的签名可以让你的信息更加突出、更具个性魅力.本文接下来就分享设计个性签名的方法,让我们一起来探讨下如何设计个性化的签名,让自己的名字成为别人眼中的独特存在.https://www.xunjiepdf.com/25693
11.自已如何做苹果app签名A:苹果自己可以签名,这是因为苹果公司拥有自己的数字证书和私钥,可以用来签名和验证软件和固件。在苹果设备中,只有经过苹果签名的软件和固件才能被安装和运行,这也是苹果设备相对于其他设备更加安全的原因之一。数字签名是一种用于验证软件或文件完整性和真实性的技术。数字详情 http://platform.yimenapp.com/ios-zhengshu-13.html
12.在线怎么做电子签名软件如何手写电子签名word/pdf亲笔签数字科技—传统的合同文件打印签章扫描存储,无法律效力,手写的签名图片,并非电子签名数据,不符合电子签名法规定.数字笔迹采用生物识别技术,区块链存证安全有效.https://www.isigning.com/jsld
13.在线合同签约时提示“电子签名中,请稍后查看”如何处理?在进行在线合同签约时,若遇到系统提示“电子签名中,请稍后查看”,这通常意味着电子签名流程尚未完成或存在某些技术障碍。面对这种情况,用户可以按照以下步骤进行处理: 步:退出电子合同签约界面 首先,用户应确保完全退出当前的电子合同签约界面。这一步的目的是确保之前的操作不会影响到后续的处理步骤。 https://www.kuaiqianpos.cn/cjwt/1565.html
14.163vip邮箱签名如何设置?个人办公邮箱签名设置方法PP视频为您提供163vip邮箱签名如何设置?个人办公邮箱签名设置方法高清视频在线观看,163vip邮箱签名如何设置?个人办公邮箱签名设置方法主要内容:https://v.pptv.com/show/wJaXBGzSQoDjYck.html
15.pdf编辑在线签字怎么弄?pdf编辑在线签字有何作用?pdf编辑在线签字是一项非常实用的技能,它可以在PDF文档中添加签名、日期和注释等信息,为文件的安全性和完整性提供保障。不过,市场上在线签字的软件或工具较多,使用方法都不一样。那么pdf编辑在线签字怎么弄?pdf编辑在线签字有何作用?本文将为大家进行详细地介绍。 https://www.foxitsoftware.cn/edit/information/2138.html
16.在桌面和在线上不容错过的12大GIF调整器如何创建签名 GIF? 创建签名 GIF 有两种主要方法。 你可以创建你自己的 GIF使用 Giphy 之类的网站,然后将其上传到在线签名制作商。 或者,您可以在在线签名制作工具中快速轻松地创建带有硬盘驱动器或在线图片的 GIF。 例如,WiseStamp 是一个动画 GIF 签名制作器。 https://www.apeaksoft.com/zh-CN/photo/gif-resizer.html
17.伪造上诉状签名这种情况应如何处理?原告的起诉状非其本人签名,应该如何处理要根据具体情况分析:1、如果诉状上并非原告本人签名,但是由原告https://www.64365.com/ask/4510677.aspx