html2canvas + jspdf 前端如何准确导出 pdf 文件?

网页中,html2canvas + jspdf 前端如何准确把指定 Dom 区域为 pdf 文件导出呢?

使用 html2canvas + jspdf 组合就可以了。
低层原理盲猜【有空也不会去看源码哈】,把 Dom 转 Image 再构建 pdf。Dom 转 Image 如何转?svg 的 forignObject 支持把 Dom 内嵌到 svg 里,然后可以通过给图片对象写入 base64 编码的 svg 流来实现。即:const image = new Image();image.src = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(mySvgXmlByHtml))),两行搞了

言归正转,使用方式如下:

    try {
      await html2Canvas(document.querySelector('#myTargetDomId'), {
        allowTaint: true, // 开启跨域
        scale: 2, // 提升画面质量,但是会增加文件大小
      }).then(canvas => {
        const contentWidth = canvas.width;
        const contentHeight = canvas.height;
        const pageHeight = (contentWidth / 592.28) * 841.89;

        let leftHeight = contentHeight;
        let position = 0;
        // a4 纸的尺寸[595.28,841.89],html 页面生成的 canvas 在 pdf 中图片的宽高
        const imgWidth = 595.28;
        const imgHeight = (592.28 / contentWidth) * contentHeight;

        const pageData = canvas.toDataURL('image/jpeg', 1.0);

        const pdf = new JsPDF('', 'pt', 'a4');

        // 有两个高度需要区分,一个是 html 页面的实际高度,和生成 pdf 的页面高度(841.89)
        // 当内容未超过 pdf 一页显示的范围,无需分页
        if (leftHeight < pageHeight) {
          pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
        } else {
          // 分页
          while (leftHeight > 0) {
            pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);
            leftHeight -= pageHeight;
            position -= 841.89;

            // position += 841.89;
            // 避免添加空白页
            if (leftHeight > 0) {
              pdf.addPage();
            }
          }
        }

        const now = new Date();
        const date = now.toLocaleDateString().replace(/\//g, '-');
        const time = now.toLocaleTimeString().replace(/:/g, '-');

        pdf.save(`我的文件名${date}_${time}.pdf`);
      });
    } catch (err) {
      // eslint-disable-next-line no-console
      console.warn(err);
    } finally {
      // finally
    }

参考引用:
https://www.cnblogs.com/eide/p/14234798.html
https://blog.csdn.net/weixin_44833875/article/details/117065423