前端实现pdf, htmltocanvas+jsPdf

·  阅读 750

背景:公司之前的pdf实现是由后端实现的,后端生成pdf后返回前端链接,前端再做处理。因为由后端的实现会消耗性能,所以打算由前端来实现。 我在百度,掘金上看了很多方案,决定用了htmltocanvas和jsPdf来实现pdf。那么开始:

1.安装两个依赖:

npm i html2canvas -S
npm i jspdf -S
复制代码

实现思路:html转换成canvas后生成图片导出pdf

html2canvas是一款将HTML代码转换成Canvas的插件,而jsPDF就是将canvas生成pdf的

2.代码的实现:

    // 做的时候页面比较长,出现了滚动条,然后截取不全,上面的部分截取不到,就需要设置页面初始位置,从最顶部开始截取
    // 设置页面的初始化的位置
    window.pageYOffset = 0;
    document.documentElement.scrollTop = 0
    document.body.scrollTop = 0

    html2Canvas(document.querySelector(`#${targetDom}`), { // targetDom是目标dom,就是要生成canvas的元素
        allowTaint: true, // 允许跨域(我也没试过,哈哈~)
        useCORS: false,// 这个好像也是运行跨域,网上还说不能和allowTaint配合使用(我也没试过,哈哈~有点尴尬)
        scale: 2, // 缩放倍数,网上说数值越大越清晰,我简单的尝试换成1.5确实模糊了一些
        // dpi: window.devicePixelRatio * 2, // window.devicePixelRatio是设备像素比
        }).then(canvas  => {
            let position = 0;

            // 生成的画布元素宽高
            let canvasWidth = canvas.width;
            let canvasHeight = canvas.height;

            // 页面等比例缩放后宽高
            let pageWidth = a4Width;
            let pageHeight = (a4Width / canvasWidth) * canvasHeight;
            
            //返回图片dataURL,参数:图片格式和清晰度(0-1)
            let jpeg = canvas.toDataURL('image/jpeg', 1.0);

            // 第一个参数是纵横向,第二个参数是单位,第三个参数是生成pdf的大小,自定义pdf大小的话可以传入一个数组,eg:[164.14, 424.5]
            //方向默认竖直,尺寸ponits,格式a4 [595.28,841.89]
            let pdf = new JsPDF('', 'pt', 'a4');
            
            //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
            //当内容未超过pdf一页显示的范围,无需分页
            if (canvasHeight < pageHeight) {
                // 第三,四个参数是图片偏移位置,第五六个参数是生成的图片的宽高
                pdf.addImage(jpeg, 'JPEG', 0, 0, pageWidth, pageHeight); // 从图片顶部开始打印
            } else {
                while (canvasHeight > 0) {
                    pdf.addImage(jpeg, 'JPEG', 0, position, pageWidth, pageHeight);
                    canvasHeight -= pageHeight;
                    position -= a4Height;

                    //避免添加空白页
                    if (canvasHeight > 0) {
                        pdf.addPage();
                    }
                }
            }
            pdf.save(fileName + '.pdf'); // fileName文件名称,自定义
        }
    )
复制代码

3.效果截图:

生成的dom页面(页面布局等是从其他地方抄来的)
点击下方的确认可以生成预览图
复制代码

长图1.jpg

预览图生成不完全,如下图:
复制代码

生成pdf不全.jpg

这时候只要在确认的时候加上这几行代码就好了
    window.pageYOffset = 0;
    document.documentElement.scrollTop = 0
    document.body.scrollTop = 0
再来看效果图:
复制代码

生成完整的pdf.jpg

最后的下载:

// pdf是new JsPDF('', 'pt', 'a4')生成的实例对象
pdf.save(title + '.pdf')
复制代码

总结:大概的pdf实现就是这样子,但是最后要对生成的pdf进行打印,打印的又是那种类似于超市开的小票的规格大小,由于生成的pdf是由图片再转成pdf的,导致打印机打印出来会失真,就不再选择由前端去实现这个需求了。小的能力有限- 有个打印的效果图可以给大家看下:

打印出来的效果对比图.png

夸一下,我的手看起来还挺白的~~哈哈哈
复制代码

题外话:这是我第一次写掘金,然后很多代码也是借鉴了大佬们的,有觉得眼熟的多多担待。有些说法描述的不对的也请大佬们指正。也是对一些觉得好玩的事的一次记录吧。希望自己以后能继续保持下去!!!

分类:
前端
分类:
前端
收藏成功!
已添加到「」, 点击更改