推广

H5基于canvas实现电子签名并生成PDF文档

iseeyu2年前 (2024-02-21)推广139

Touch.png

clientX/clientY: 触摸位置距离当前body可视区域的x,y坐标;
pageX/pageY: 对于整个页面来说,触摸位置距离body左上角的x,y坐标,包括被scrollTop和scrollLeft的值;
screenX/screenY: 触摸位置距离显示器左边和顶部的x,y距离。
所以,在获取结束点坐标的时候,如果当前页面没有出现滚动条,使用clientY和pageY计算差别不大,如果页面比较长,出现了滚动条,那么就必须要使用pageY来计算。clientX同理,但是移动端通常横向滚动的场景不多,所以用clientX来计算即可。

  1. 在签名(touchmove)这个动作过程中,我们需要不断的更新起点位置,否则画出来是这样

    touchmove.png

    其实这个原理和微积分很相似,线段本质上就是由无穷多个小线段组成,宏观一点来看可以把线段当成一个个长度很小的小线段首尾相连构成。所以我一直觉得编程编到最后就是考验一个人的数学能力,交并集、逻辑思维、算法等都能看到数学的身影。

生成PDF文档

html2canvas是一款将HTML代码转换成Canvas的插件,因此需要用一个div包裹住需要打印的内容区域,获得这个dom节点。

html2Canvas(dom, {
    allowTaint: true,
    width: dom.offsetWidth, //设置获取到的canvas宽度
    height: dom.offsetHeight, //设置获取到的canvas高度
    x: 0, //页面在水平方向滚动的距离
    y: 0, //页面在垂直方向滚动的距离
   })

注意:此处需要设置width和height及x,y,否则当页面内容只有一页的时候没有题,但是若页面内容有很多页的时候,就会出现生成的图片只有一小部分有内容的现象。问题就出现在这个配置参数上,若没有设置宽高,则默认只取当前视口的内容,丢弃掉其他超出当前视口的内容。
设置打印参数:

const print = () => {
    let dom: HTMLElement = pdfDom.current;
    html2Canvas(dom, {
      allowTaint: true,
      width: dom.offsetWidth, //设置获取到的canvas宽度
      height: dom.offsetHeight, //设置获取到的canvas高度
      x: 0, //页面在水平方向滚动的距离
      y: 0, //页面在垂直方向滚动的距离
    }).then((canvas: HTMLCanvasElement) => {
      let canvasWidth = canvas.width;
      let canvasHeight = canvas.height;
      let pageHeight = (canvasWidth / 592.28) * 841.89; // 一页A4 pdf能显示的canvas高度
      let imgWidth = 595.28; // 设置图片宽度和A4纸宽度相等
      let imgHeight = (592.28 / canvasWidth) * canvasHeight;//等比例换算成A4纸的高度
      let totalHeight = imgHeight; // 需要打印的图片总高度,初始状态和图片高度相等
      let pageData = canvas.toDataURL('image/png', 1.0);
      let PDF = new JsPDF('p', 'pt', 'a4', true);
      if (totalHeight < pageHeight) { //
        PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight); // 从顶部开始打印
      } else {
        let top = 0;   // 打印初始区域
        while (totalHeight > 0) {
          PDF.addImage(pageData, 'JPEG', 0, top, imgWidth, imgHeight);  // 从图片顶部往下top位置开始打印
          totalHeight -= pageHeight;
          top -= 841.89;
          if (totalHeight > 0) {
            PDF.addPage();
          }
        }
      }
      PDF.save('test.pdf');
    });
  };

选择分页位置

按照上述步骤生成了一份PDF文档,但是当PDF页数有很多的时候,会有这样的问题

pdf.png

可以看到,分页的时候从这段文字这里懒腰截断了。这显然不是我们想要看到的效果,如何解决这个问题呢?

  • PDF文档页数较少的情况
    可以在开发测试的时候预先在将要分页的地方插入一个padding,就是提前预留分页位置

  • PDF文档页数较多

对于这种情况,笔者尝试遍历要打印的dom节点的子节点,将每一页所能打印的dom节点高度累加,若超过了页面所能承载的最大高度,则将最后一个节点增加padding,打印完毕将样式还原。这种方法因为要计算每个dom节点的高度,非常耗性能,也要求页面dom元素的颗粒度较细,否则会出现一个页面有大块空白,完全无法模拟出word生成pdf的那种效果,所以就不展开讨论了。这里也有个参考关于pd分页stackoverflow.com

源码地址

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/57478.html

相关文章

如何用小红书打造出爆款网红产品

如何用小红书打造出爆款网红产品

为了便于理解这篇文章,先给大家讲一个概念:AISAS模式。百科词条解释是电通公司针对互联网与无线应用时代消费者生活形态的变化,而提出的一种全新的消费者行为分析模型。通俗解释是移动互联网用户的消费模式。 AISAS模式即Attention—注意,Interest—兴趣,Searc...

漳州急寻:六旬老太走失,患抑郁症,穿深蓝色卡通长款睡衣,没有牙齿,消瘦

漳州急寻:六旬老太走失,患抑郁症,穿深蓝色卡通长款睡衣,没有牙齿,消瘦

走失者姓名:田达秀走失者性别:女走失者年龄:61走失者特征:穿深蓝色卡通长款睡衣、黑色皮鞋,没有牙齿,消瘦,目光呆滞,患抑郁症走失时间:2021-05-06走失地点:福建,漳州市,芗城区 浦南镇联系人:家属联系电话:18692501086,18574513002其他信息:今...

网站排名第一了。

网站排名第一了。

3、搜索算法 毫无疑问,百度每天都会进行大量算法的测试与细微的迭代,每一弱小的影响因子,都可能会产生不同的影响,比如: ①搜索引擎可能可能会审查网站内容质量,调整合理的预期排名。 ②搜索引擎惩罚过度的seo优化,比如:堆积关键词,短期大量购买外部链接。 ③搜索引擎严厉打击刷排名,SEO快...

淘宝行业核心词是什么词(商品的核心词)

淘宝行业核心词是什么词(商品的核心词)

核心词是和商品的属性相符的关键词。用户在手机淘宝上搜索关键词,如果我们的宝贝能够展现在前排,就会有很多流量涌进,有流量了,就意味着订单会增多。大家在写关键词的时候,应该合理分配,掌握好商品上下架的时间。...

4大主流平台信息流优化案例,这波干货很及时~

4大主流平台信息流优化案例,这波干货很及时~

对于 信息流广告而言,广告的内容和创意是广告主和代理商们最有发挥空间与提升潜力的环节。那么,在不同平台的媒体环境中, 什么样的广告才能有效完成转化,取得最佳效果? 有哪些前车之鉴值得注意?今天艾奇菌从 社交、 电商、家装、 O2O等行业的投放案例入手,一起通过以下案例实现多...

新网站应如何提高排名。

新网站应如何提高排名。

每一位站长在做新站的时候都希望自己的网站排名可以高人一筹,因为一个排名靠前的网站可以获得相对稳定的流量,而这些流量慢慢的就会转化成网站的收益。对于每个站长来说,收益是一个网站继续生存下去的资本,也是站长继续维护网站的一块基石。但是如何提高一个新网站的排名呢?这是站长们都非常重视的问题,也让站长们绞尽...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片