jsPDF参考:https://github.com/parallax/jsPDF
html2canvas参考:https://github.com/niklasvh/html2canvas 或者 https://html2canvas.hertzen.com

思路

  1. 使用html2canvas将选中DOM生成截图对象
  2. 将截图对象借助jsPDF导出为PDF文件

代码

这是一个示例,内容都放在了单个页面进行静态引用

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>协议</title>
    <script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.debug.js"></script>
</head>
<style>
    body {
        /* font-family: Arial, sans-serif; */
        text-align: center;
        margin-top: 50px;
    }
    .contentBox {
        text-align: left;
        margin: 0vh 8vw;
    }
    h1 {
        color: #333;
    }
    p {
        font-size: 20px;
        line-height: 1.5;
    }
    .canvasBox {
        border: #333 0.5px solid;
        height: 85vh;
    }
</style>

<body>
    <div id="xieyi" class="canvasBox">
        <h1>协议</h1>
        <p>在此文本中,我们将声明有关事项的协议。</p>  
        <p>请仔细阅读以下条款,并在同意后继续使用我们的服务。</p>  
        <h2>条款一:服务使用</h2>
        <div class="contentBox">
            <p><strong>1、服务使用:</strong>本协议规定了您使用我们服务的条款和条件。</p>
        </div>
        <h2>条款二:隐私保护</h2>
        <div class="contentBox">
            <p><strong>1、隐私保护:</strong>我们将保护您的个人信息和隐私。</p>
        </div>
    </div>
    <button onclick="exportPDF()" style="margin: 2%;">保存</button>
</body>
<script>
    // 获取时间
    function getDateTime() {
        let myDate = new Date();
        let year = myDate.getFullYear();
        let month = myDate.getMonth() + 1;
        let day = myDate.getDate();
        let hours = myDate.getHours();
        let minutes = myDate.getMinutes();
        let seconds = myDate.getSeconds();
        let time = `${year}-${month}-${day}-${hours}_${minutes}_${seconds}`;
        return time;
    }
    function exportPDF() {
        var contentBox = document.getElementById('xieyi');
        // console.log(contentBox.offsetHeight)
        let domHeight = contentBox.offsetHeight;
        let maxHeight = 64257;

        html2canvas(contentBox, {
            useCORS: true, // 如果截图的内容里有图片,可能会有跨域的情况,加上这个参数,解决文件跨域问题
            scale: (maxHeight / domHeight) > 1 ? 1 : (maxHeight / domHeight)
        }).then((canvas) => {
            const contentWidth = canvas.width;
            const contentHeight = canvas.height;

            let pageHeight = contentWidth / 592.28 * 841.89;
            let leftHeight = contentHeight;

            //页面偏移
            var position = 0;
            //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
            var imgWidth = 595.28; // A4 宽度
            var imgHeight = 592.28 / contentWidth * contentHeight; // A4总高度
            var pageData = canvas.toDataURL('image/jpeg', 1);
            var pdf = new jsPDF('p', 'pt', 'a4');
            //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
            //当内容未超过pdf一页显示的范围,无需分页
            if (leftHeight < pageHeight) {
                pdf.addImage(pageData, 'JPEG2000', 10, 10, imgWidth - 20, imgHeight);
            } else {
                while (leftHeight > 0) {
                    pdf.addImage(pageData, 'JPEG2000', 10, position + 10, imgWidth - 20, imgHeight)
                    leftHeight -= pageHeight;
                    position -= 841.89;
                    //避免添加空白页
                    if (leftHeight > 0) {
                        pdf.addPage();
                    }
                }
            }
            let fileName = "XXX协议" + getDateTime();
            pdf.save(fileName);
        })
    }
</script>

</html>

效果

因为计算了生成截图对象时的宽高,所以相对适配
通过html2canvas和jsPDF将网页内容导出成pdf-LMLPHP
通过html2canvas和jsPDF将网页内容导出成pdf-LMLPHP

宽高参考

        'a0': [2383.94, 3370.39],
        'a1': [1683.78, 2383.94],
        'a2': [1190.55, 1683.78],
        'a3': [841.89, 1190.55],
        'a4': [595.28, 841.89],
        'a5': [419.53, 595.28],
        'a6': [297.64, 419.53],
        'a7': [209.76, 297.64],
        'a8': [147.40, 209.76],
        'a9': [104.88, 147.40],
        'a10': [73.70, 104.88],
        'b0': [2834.65, 4008.19],
        'b1': [2004.09, 2834.65],
        'b2': [1417.32, 2004.09],
        'b3': [1000.63, 1417.32],
        'b4': [708.66, 1000.63],
        'b5': [498.90, 708.66],
        'b6': [354.33, 498.90],
        'b7': [249.45, 354.33],
        'b8': [175.75, 249.45],
        'b9': [124.72, 175.75],
        'b10': [87.87, 124.72],
        'c0': [2599.37, 3676.54],
        'c1': [1836.85, 2599.37],
        'c2': [1298.27, 1836.85],
        'c3': [918.43, 1298.27],
        'c4': [649.13, 918.43],
        'c5': [459.21, 649.13],
        'c6': [323.15, 459.21],
        'c7': [229.61, 323.15],
        'c8': [161.57, 229.61],
        'c9': [113.39, 161.57],
        'c10': [79.37, 113.39],
        'dl': [311.81, 623.62],
        'letter': [612, 792],
        'government-letter': [576, 756],
        'legal': [612, 1008],
        'junior-legal': [576, 360],
        'ledger': [1224, 792],
        'tabloid': [792, 1224],
        'credit-card': [153, 243]
02-04 16:06