美文网首页程序员
js依赖网页打印实现自动分页和纸张大小设定

js依赖网页打印实现自动分页和纸张大小设定

作者: Eason_0cce | 来源:发表于2023-12-05 21:04 被阅读0次

    先看效果:


    image.png

    上代码:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <div class="print pickingPrint" id="pickingPrint">
        </div>
    </body>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        /* 详细设置:https://developer.mozilla.org/en-US/docs/Web/CSS/@page */
        @media print {
            @page {
                margin: 0mm;
                size: a4 landscape;
                msn-header: none;
                msn-footer: none;
            }
    
            .noPrint {
                display: none;
            }
        }
    
        .pickingPrint {
            margin: 0;
            font-size: 14px;
            box-sizing: border-box;
        }
    
        .pickingPrint h3 {
            font-size: 26px;
            text-align: center;
            font-weight: normal;
            height: 35px;
        }
    
        .pickingPrint .flex {
            display: flex;
        }
    
        .pickingPrint .flex1 {
            flex: 1;
        }
    
        .pickingPrint .just-right {
            justify-content: flex-end;
        }
    
        .pickingPrint .align-center {
            align-items: center;
        }
    
        .pickingPrint .flex-wrap {
            flex-wrap: wrap;
        }
    
        .pickingPrint .head {
            padding: 15px 0;
            white-space: nowrap;
            line-height: 1.5em;
            height: 72px;
            box-sizing: border-box;
        }
    
        .pickingPrint .headCode {
            padding-left: 8%;
            position: relative;
        }
    
        .pickingPrint .headCode .qrCode {
            position: absolute;
            top: 0;
            left: 0;
        }
    
        .pickingPrint .tableHead {
            height: 27px;
        }
    
        .pickingPrint .head .item1 {
            width: 35%;
        }
    
        .pickingPrint .head .item2 {
            width: 28.5%;
            padding-left: 5.5%;
        }
    
        .pickingPrint .head .item3 {
            width: 21%;
        }
    
        .pickingPrint .headCode .item1 {
            width: 35%;
        }
    
        .pickingPrint .headCode .item2 {
            padding-left: 0;
            width: 30%
        }
    
        .pickingPrint .headCode .item3 {
            width: 30%;
        }
    
        .pickingPrint .table .item {
            padding: 4px 2px;
            box-sizing: border-box;
            align-items: center;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: flex-start;
        }
    
        .pickingPrint .table .item1 {
            width: 12%;
        }
    
        .pickingPrint .table .item2 {
            width: 12%;
        }
    
        .pickingPrint .table .item3 {
            flex: 1;
        }
    
        .pickingPrint .table .item4 {
            width: 10%;
        }
    
        .pickingPrint .table .item5 {
            width: 12%;
        }
    
        .pickingPrint .table .item6 {
            width: 10%;
        }
    
        .pickingPrint .table .item7 {
            width: 7%;
        }
    
        .pickingPrint .table .item8 {
            width: 8%;
        }
    
        .pickingPrint .table .item .number~.number {
            border-top: 1px solid #eee;
        }
    
        .pickingPrint .tableBox {
            border: 1px solid #999;
            border-bottom: 0;
            font-size: 12px;
            box-sizing: border-box;
        }
    
        .pickingPrint .tableBox .table {
            border-bottom: 1px dashed #999;
        }
    
        .pickingPrint .tableBox .table:last-child {
            border-bottom-style: solid;
        }
    
        .pickingPrint .page {
            height: 19px;
            font-size: 14px;
            align-items: center;
        }
    
        .pickingPrint .break {
            page-break-after: always
        }
    </style>
    <script>
        var tmpNode = document.createElement("DIV");
        tmpNode.style.cssText = "width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";
        document.body.appendChild(tmpNode);
        const xdpi = tmpNode.offsetWidth;
        const ydpi = tmpNode.offsetHeight;
        tmpNode.parentNode.removeChild(tmpNode);
        const widthValue = Math.floor(xdpi / 2.54 * 21);
        const heightValue = ydpi / 2.54 * 29.7;
        document.querySelector("#pickingPrint").style.width = `${heightValue}px`;
        const date = new Date();
        const zoneOffset = date.getTimezoneOffset();
        let offsetHour = Math.abs(zoneOffset / 60);
        let offsetHourString = "";
        if (zoneOffset <= 0) {
            offsetHourString = `+${offsetHour}`
        }
        if (zoneOffset > 0) {
            offsetHourString = `-${offsetHour}`
        }
        const lanSet = {
            cn: {
                title: '标题',
                number: "字段",
                typeNumber: "字段",
                totalNumber: "字段",
                printedBy: "字段",
                printTime: "字段",
                printingTimes: "字段",
                barCode: "字段",
                sku: "字段",
                goodName: '字段',
                specification: "字段",
                brand: "字段",
                classification: "字段",
                quantity: "字段",
                gift: "字段",
                page: "字段"
            }
        };
        renderPage(0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], 'cn');
        function renderPage(index, list, lan) {
            const char1 = `${lanSet[lan].number}: 字段`;
            const char2 = `${lanSet[lan].typeNumber}:1`;
            const char3 = `${lanSet[lan].totalNumber}:1`;
            const char4 = `${lanSet[lan].printedBy}:管理员账号`;
            const char5 = `${lanSet[lan].printTime}: ${date.toLocaleDateString() + " " + date.toLocaleTimeString()} ${offsetHourString}`;
            const char6 = `${lanSet[lan].printingTimes}: ${index + 1}`;
            const char7 = `OWCU/${lanSet[lan].barCode}`;
            const char8 = `sku/${lanSet[lan].sku}`;
            const char9 = `${lanSet[lan].goodName}`;
            const char10 = `${lanSet[lan].specification}`;
            const char11 = `${lanSet[lan].brand}`;
            const char12 = `${lanSet[lan].classification}`;
            const char13 = `${lanSet[lan].quantity}`;
            const char14 = `${lanSet[lan].gift}`;
            const pageItem = document.createElement("div");
            pageItem.style.padding = `${ydpi / 2.54}px`;
            pageItem.innerHTML = `
            <h3>${lanSet[lan].title}</h3>
            <div class="flex flex-wrap head">
                <div class="item1">${char1}</div>
                <div class="item2">${char2}</div>
                <div class="item3">${char3}</div>
                <div class="item1">${char4}</div>
                <div class="item2">${char5}</div>
                <div class="item3">${char6}</div>
            </div>
            <div class="flex table tableHead">
                <div class="item item1">${char7}</div>
                <div class="item item2">${char8}</div>
                <div class="item item3">${char9}</div>
                <div class="item item4">${char10}</div>
                <div class="item item5">${char11}</div>
                <div class="item item6">${char12}</div>
                <div class="item item7">${char13}</div>
                <div class="item item8">${char14}</div>
            </div>
    
            <div class="tableBox">
    
            </div>
    
            <div class="flex just-right page">${index + 1}/<span class="totalPage"></span>${lanSet[lan].page}</div>
            `;
            if (index > 0) {
                pageItem.classList.add("break");
            }
            document.querySelector("#pickingPrint").appendChild(pageItem);
            document.querySelectorAll("#pickingPrint .totalPage").forEach(totalPage => {
                totalPage.innerText = index + 1;
            });
            renderItem(0);
            console.log(widthValue * (index + 1), "1111");
            function renderItem(itemIndex) {
                const item = list[itemIndex];
                const tableItem = document.createElement("div");
                tableItem.className = "flex table";
                tableItem.innerHTML = `
                <div class="item item1">
                        <div class="number">字段</div>
                        <div class="number">字段</div>
                    </div>
                    <div class="item item2">
                        <div class="number">字段</div>
                        <div class="number">字段</div>
                    </div>
                    <div class="item item3">字段</div>
                    <div class="item item4">字段</div>
                    <div class="item item5">字段</div>
                    <div class="item item6">字段</div>
                    <div class="item item7">${itemIndex}</div>
                    <div class="item item8">字段</div>
                `;
                document.querySelectorAll("#pickingPrint .tableBox")[index].appendChild(tableItem);
                if (pageItem.offsetHeight > widthValue) {
                    //有下一页
                    document.querySelectorAll("#pickingPrint .tableBox")[index].removeChild(tableItem);
                    if (list.slice(itemIndex, list.length).length > 0) {
                        renderPage(index + 1, list.slice(itemIndex, list.length), lan);
                    } else {
                        window.print();
                    }
                } else {
                    //没有下一页
                    if (list[itemIndex + 1]) {
                        renderItem(itemIndex + 1);
                    } else {
                        // 没有数据了
                        window.print();
                    }
                }
            }
        }
    </script>
    
    </html>
    

    核心点:
    1、计算A4纸张在宿主屏幕中的实际大小,计算方法:设置一个1英寸的元素,根据实际大小算出实际占用像素,然后根据宽高像素值反推A4纸大小。
    2、根据元素动态创建高度,实现分页,分页样式: page-break-after: always
    3、设置打印样式:@media print,详细参数见备注链接,我将页面大小设置成了auto,因为我前面已经精准算出了分页符的位置,所以打印时候会自动分页。也就是每页都会分成A4纸的大小。

    拓展:
    电商类的标签打印,也可以使用这个方案,比如打印100*100的物流面单。可以动态插入一条打印样式

    @media print { @page {  size:${width}px ${height}px;  }}
    

    相关文章

      网友评论

        本文标题:js依赖网页打印实现自动分页和纸张大小设定

        本文链接:https://www.haomeiwen.com/subject/qavdgdtx.html