chrome下打印的一种思路

    使用html2canvas+pdfmake

    先使用html2canvas将网页转化成canvas对象,从canvas中生成图像数据,再利用pdfmake将其转成pdf进行打印

    这种方法具有普适性,不用管dom节点的具体内容。主要解决了分页和自定义页眉页脚的问题,通过pdfmake也可以自定义很多文档属性等内容。

    遗留的主要问题是分页时会出现同一个字或图片变成两半的问题

    另外在我的项目中使用pdfmake需要手动去替换node_modules目录下的vfs_fonts文件来显示中文或更换字体(我将vfs_fonts.js手动拷贝到项目中并引入时会报错,vfs_fonts.js代码里的this为undefined,目前尚未找到原因和好的解决方案),而在原生js中则没有这个问题,目前还不清楚原因。

    对于html打印,目前提供的解决思路如下:

    1、 先将获取到的dom节点进行缩放(使用transform),使其适应于打印纸张的尺寸,然后使用table,利用thead和tfoot可以在每页显示的特征来作为页眉和页脚。 目前我还未找到一个显示页码的方式(页眉页脚是固定的),以及没有较好的排班方式,该方式是可以较好的进行分页的。

    2、 确定页面尺寸,在每页放置head,main和foot三个部分,即页眉页脚和打印主体内容,针对打印主体设置margin-top,使其出现分页的显示效果。 该方法可行,但也会出现分页不合理的问题

    3、使用html2canvas+jspdf,该方法网上有教程,显示页眉页脚的时候也类似于方法2,需要手动控制尺寸,生成页眉和页脚的html代码,

    4、使用html2canvas+pdfmake,该方法可以方便的设置页眉页脚,和3的区别不大,但目前pdfmake好像不支持页眉和页脚设置成图片。

    5、(只是个想法)遍历节点,手动进行分页等操作(在合适的位置插入页眉和页脚,针对不同的标签情况进行分页),如果想用这种方法去实现普适性的打印的话,过于复杂。

 

    chrome原生打印存在的主要问题就是很多东西都没办法自定义(ie等浏览器也是,各浏览器情况不同,也分轻重)

无法较为复杂的打印需求。目前的解决方法还不完善,对比1~4四种方法,4的表现最好,代码也最简洁。

    代码如下(在react项目里, 主要方法是cutImg和print):

/**
 * Created by Siver on 2018/7/11.
 * ReactDomPrinter节点转化为pdf进行打印
 */
import React from 'react'
import PropTypes from 'prop-types'
import html2canvas from 'html2canvas'
import pdfMake from 'pdfmake/build/pdfmake'
import pdfFonts from 'pdfmake/build/vfs_fonts'

export default class ReactDomPrinter extends React.Component {
    static propTypes = {
        /** Dom'id to print */
        domID: PropTypes.string.isRequired,
        pageHeight: PropTypes.number,
        pageWidth: PropTypes.number,
        margin: PropTypes.shape({
            left: PropTypes.number,
            top: PropTypes.number,
            right: PropTypes.number,
            bottom: PropTypes.number,
        }),
        header: PropTypes.oneOfType([
            PropTypes.object,
            PropTypes.func,
        ]),
        footer: PropTypes.oneOfType([
            PropTypes.object,
            PropTypes.func,
        ]),
        pageSize: PropTypes.string,
    };

    //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
    static defaultProps = {
        pageHeight: 841.89,
        pageWidth: 595.28,
        margin: {
            left: 20,
            top: 30,
            right: 20,
            bottom: 30
        },
        header: {
            columns: [
                {text: 'begin', alignment: 'left', margin: 5},
                {text: 'end', alignment: 'right', margin: 5}
            ]
        },
        footer: (currentPage, pageCount) => {
            return {
                text: currentPage.toString() + '/' + pageCount,
                alignment: 'center',
                margin: 5
            };
        },
        pageSize: 'A4'
    };

    constructor(props) {
        super(props);

        pdfMake.vfs = pdfFonts.pdfMake.vfs;

        this.state = {
            domID: this.props.domID
        }
    }

    componentWillReceiveProps(next) {
        if (next.domID !== this.props.domID) {
            this.setState({
                domID: next.domID
            });
        }
    }

    print = () => {
        let dom = document.getElementById(this.state.domID);
        html2canvas(dom).then(canvas => {
            const PAGE_H = this.props.pageHeight;
            const PAGE_W = this.props.pageWidth;
            const margin = this.props.margin;

            let IMG_W = PAGE_W - margin.left - margin.right;
            let IMG_H = PAGE_H - margin.top - margin.bottom;
            let pageData = canvas.toDataURL('image/jpeg', 1.0);
            let docDefinition = {
                pageSize: this.props.pageSize,
                footer: this.props.footer,
                header: this.props.header,
                pageMargins: [margin.left, margin.top, margin.right, margin.bottom],
            };
            //每页显示的实际图片高度;
            let pageHeight = canvas.width / IMG_W * IMG_H;
            //页面偏移
            let top = 0;
            //content
            let content = [];
            //当内容未超过pdf一页显示的范围,无需分页
            if (canvas.height < pageHeight) {
                content.push({
                    image: pageData,
                    margin: [0, 0],
                    width: IMG_W,
                    height: canvas.height * IMG_W / canvas.width
                });
            } else {
                while (top < canvas.height) {
                    let cutHeight = top + pageHeight > canvas.height ? canvas.height - top : pageHeight;
                    let obj = {
                        image: this.cutImg(canvas, cutHeight, canvas.width, top, 0),
                        margin: [0, 0],
                        width: IMG_W,
                        height: cutHeight * IMG_W / canvas.width,
                    };
                    top += pageHeight;
                    //分页
                    if (top < canvas.height) obj.pageBreak = 'after';
                    content.push(obj);
                }
            }
            docDefinition.content = content;
            pdfMake.createPdf(docDefinition).open();
        });
    };


    //canvas对图片进行裁剪
    cutImg = (imgData, height, width, top, left) => {
        let canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        canvas.getContext('2d').drawImage(imgData, left, top, width, height, 0, 0, width, height);
        // 保存图片信息
        return canvas.toDataURL('image/jpeg', 1.0);
    };

    render() {
        return (
            <button onClick={this.print}>打印</button>
        )
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值