天行健
君子以自强不息
地势坤
君子以厚德载物

HTML转换成pdf文件[代码篇]

  |   0 评论   |   0 浏览

之前做过一个在线签名的功能,具体的需求是,用户可以在线签名,可以对签名进行编辑,最终生成pdf的功能.

这次不聊在线签名,只谈html代码最后生成pdf导

这个功能需要用到两个组件来配合,先把html转换成canvas,然后在使用jspdf对canvas进行转换并下载

组件名称:[html2canvas],[jspdf],代码在github上,gitee也有,搜索名字就可以查到:yylcha.smooth-signature

  1. github地址

打开SmoothSignature_CSharp版本即可,另外一个是vue版的

image.png

项目资源文件介绍

引用 html2canvas.js | jspdf.js 你copy过去也可以直接使用,这两个js是我们核心使用文件

image.png

js引用

image.png

HTML Code


<div>
    <div class="singPanel" id="overtimeApp">
        <table class="cssTb">
            <tr>
                <td>部门</td>
                <td></td>
                <td>姓名</td>
                <td>XXX</td>
                <td>职位</td>
                <td>.net开发</td>
            </tr>
            <tr>
                <td>加班事由</td>
                <td colspan="5">测试</td>
            </tr>
            <tr>
                <td>加班时间</td>
                <td colspan="5">
                    <span>日期:__2099__年__12__月__31__日(□工作日 □双休日 □国定假日)</span>
                    <br />
                    <span>时间:从__08__点到__18__点</span><br />
                    <span>共计__8__小时</span>
                </td>
            </tr>
            <tr>
                <td>换算方式</td>
                <td colspan="5"><span>□调休 □调休延期 □加班费</span></td>
            </tr>
            <tr>
                <td>实际加班时数(由HR填写)</td>
                <td colspan="3"></td>
                <td>人力资源部签收</td>
                <td></td>
            </tr>
        </table>
        <div class="cssWorld">
            <div style="float: left; width: 600px;margin-top:5px">
                <div style="float: left">申请部门经理签字:</div>
                <div class="dvCanvas">
                    <canvas style="border: 1px solid black"></canvas>
                </div>
            </div>
            <div style="float: right; width: 200px">
                  2099年  12月  31日
            </div>
            <div hidden id="hdnSignature"></div>
        </div>
    </div>
    <div class="cssBtn">
        <button class="btn btn-primary btn-sm" type="button" id="btnClear">清空签名</button>
        <button class="btn btn-primary btn-sm" type="button" id="btnUndo">撤销</button>
        <button class="btn btn-primary btn-sm" type="button" id="btnGeneraCanvas">确定</button>
        <button class="btn btn-primary btn-sm" type="button" id="btnHandleColor">修改字迹颜色</button>
        <br />
        <br />
        <button class="btn btn-primary" type="button" id="btnDownLoad">生成PDF</button>
    </div>

JavaScript Code


    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/jquery/dist/jquery.js"></script><script src="~/js/smooth-signature.min.js"></script>
    <script src="~/js/smooth-signature.js">
    </script><script src="~/js/html2canvas.js"></script><script src="~/js/jspdf.js"></script>
    <script>

        $(function () {
            //获取定义画布
            let canvas = document.querySelector("canvas");
            //画布参数
            let options = {
                width: Math.min(window.innerWidth, 370),//宽度
                height: 200,//高度
                minWidth: 4,
                maxWidth: 12,
                // color: '#1890ff',
                bgColor: "#f6f6f6",
            };
            //初始化smoothsignature画布
            var signature = null;
            if (canvas) {
                signature = new SmoothSignature(canvas, options);
            }

            //生成pdf时间
            $("#btnDownLoad").click(function () {
                //需要打印的html
                var html = document.getElementById("overtimeApp");

                //使用html2canvas把html元素转换成canvas
                //jsPDF 把canvas转换成pdf并导出
                html2canvas(html).then(function (canvas) {
                    //获取html转成canvas的宽度和高度
                    var canvasWidth = canvas.width;
                    var canvasHeight = canvas.height;

                    // 创建PDF文档对象
                    var pdf = new jsPDF('p', 'pt', 'a4');

                    //通过canvas的宽高计算pdf页面的大小,自适应pdf
                    var scaleFactor = pdf.internal.pageSize.width / canvasWidth;
                    var scaleHeight = canvasHeight * scaleFactor;

                    // 将canvas转化为图片并添加至PDF文档
                    pdf.addImage(canvas.toDataURL('image/png'), 'JPEG', 20, 30, pdf.internal.pageSize.width - 40, scaleHeight);

                    // 下载PDF文档
                    pdf.save('加班申请单.pdf');
                });
            });

            //清除签名画布
            $("#btnClear").click(function () {
                if (signature) {
                    signature.clear();
                } else {
                    alert("画布初始化失败!");
                }
            });

            //返回上一步
            $("#btnUndo").click(function () {
                if (signature) {
                    signature.undo();
                } else {
                    alert("画布初始化失败!");
                }
            });

            //把签名画布转换成image标签-未使用
            $("#btnGeneraCanvas").click(function () {
                if (signature) {
                    var pngUrl = signature.getPNG();
                    var blob = this.dataURLToBlob(pngUrl);
                    var url = window.URL.createObjectURL(blob);
                    $("#hdnSignature").attr(`<img src='${url}'></img>`)
                } else {
                    alert("画布初始化失败!");
                }
            });
            //更改笔线颜色
            $("#btnHandleColor").click(function () {
                if (signature) {
                    signature.color = "#" + Math.random().toString(16).slice(-6);
                } else {
                    alert("画布初始化失败!");
                }
  
            });

        })
        //把image转换成blob
        function dataURLToBlob(dataURL) {
            // Code taken from https://github.com/ebidel/filer.js
            const parts = dataURL.split(";base64,");
            const contentType = parts[0].split(":")[1];
            const raw = window.atob(parts[1]);
            const rawLength = raw.length;
            const uInt8Array = new Uint8Array(rawLength);

            for (let i = 0; i < rawLength; ++i) {
                uInt8Array[i] = raw.charCodeAt(i);
            }

            return new Blob([uInt8Array], { type: contentType });
        }
    </script>

Css Code


    <style>
        .cssSign {
            height: 200px;
            width: 440px;
            float: right;
        }

        .cssTb {
            margin: auto;
            width: 40%;
        }

        .cssWorld {
            margin: auto;
            width: 40%;
        }

        table,
        td {
            border: 1px solid black;
            width: 500px;
        }

        .cssBtn {
            margin-top: 300px;
            text-align: center;
        }

        .singPanel {
            width: 100%;
            height: 400px;
        }
    </style>

问题整理

为什么不直接使用jspdf来实现html转换成pdf呢?

这个问题我试过,jspdf是支持把html直接导出成pdf的,但是会有一个问题,中文会出现乱码的

再加上原来的签名组件是一个canvas,所以我使用了这个办法,后续其他的项目应用我也都是这样处理的

它的工作原理是,帮你把html代码转换成canvas,然后jspdf把canvas转换成pdf,最后导出


标题:HTML转换成pdf文件[代码篇]
作者:Jacky1994
地址:https://www.yyliucha.com/articles/2024/03/29/1711703792788.html