• 前端技术使网页生成PDF预览并下载


    前端技术使网页生成PDF预览并下载,使用jsPDFhtml2Canvas,调用getPdfFun()即可。

    import {createApp, reactive, toRefs} from "vue";
    import jsPDF from "jspdf";
    import html2Canvas from "html2canvas";
    setup() {
        const state = reactive({
            htmlTitle: 'PDF文件名',
            Height: document.documentElement.clientHeight - 180,
            pdfProgress: 1,
            pdfPage: 1,
            pdfTotal: null,
            type: '01', // 01预览 02下载
            pdfContent: { content: '我是内容' },
            isDownloaded: false, // 是否生成PDF
            isOver: false, // 是否生成完毕
            a4Width: 415.28,
            // a4Width: 595.28,
            a4Height: 841.89,
            pdf: null,
            canvas: [],
            a4HeightRef: 0,
            position: 0,
            leftHeight: 0,
            pageFooter: null,
            canvasFooter: null,
            pageTitle: null,
            canvasTitle: null,
            canvasIndex: 0,
            pageData: null,
            isAddPage: false,
            canvas1: null,
            list: [],
        })
        const getPdfFun = () => {
            // 初始化PDF
            state.pdf = new jsPDF('', 'pt', 'a4')
            state.pdf.page = 1
            state.pdf.setDisplayMode('fullwidth', 'continuous', 'FullScreen')
            state.isDownloaded = true
            if (state.type === '01') {
                console.log(state.pdf, 'pdfthis');
                getPdf(state.htmlTitle, true)
            } else if (state.type === '02') {
                getPdf(state.htmlTitle, false)
            }
        };
        const getPdf = async (title, show) => {
            // 生成页眉图片
            state.canvasTitle = await html2Canvas(document.getElementById('title'))
            state.pageTitle = state.canvasTitle.toDataURL('image/jpeg', 1.0)
            // 生成内容 6个案件点的图片
            const doms = document.getElementsByClassName('casepoint')
            console.log(doms, 'doms');
            for (let i = 0; i < doms.length; i++) {
                if (doms[i]) {
                    const canvas = await html2Canvas(doms[i], {
                        allowTaint: true,
                        scale: 2
                    })
                    state.canvas.push(canvas)
                }
            }
            state.canvas1 = document.createElement('canvas')
            // 一页pdf显示html页面生成的canvas高度; -300为了每页PDF头部和底部留有空位
            state.a4HeightRef = Math.floor(state.canvas[0].width / state.a4Width * state.a4Height)-200;
            state.position = 0
            addPage()
            for (let canvasIndex = 0; canvasIndex < state.canvas.length; canvasIndex++) {
                state.position = 0
                // 未生成pdf的html页面高度
                state.leftHeight = state.canvas[canvasIndex].height
                createImpl(state.canvas[canvasIndex])
            }
            const that = this
            // 根据生成的页数,给每一页PDF加上页码
            state.isAddPage = true
            for (let page = 0; page <= state.pdfProgress; page++) {
                state.canvasFooter = await html2Canvas(document.getElementById('footer'))
                state.pageFooter = state.canvasFooter.toDataURL('image/jpeg', 1.0)
                state.pdf.setPage(page)
                if (state.pdfPage < state.pdfProgress) {
                    state.pdfPage++
                }
                // 添加页眉
                state.pdf.addImage(state.pageTitle, 'JPEG', 90, 40, state.a4Width, (state.a4Width / state.canvasTitle.width * state.canvasTitle.height).toFixed(2) / 1)
                // 添加页码
                state.pdf.addImage(state.pageFooter, 'JPEG', 90, state.a4Height-40, state.a4Width, (state.a4Width / state.canvasFooter.width * state.canvasFooter.height).toFixed(2) / 1)
            }
            // 所有内容都生成完毕
            if (!show) {
                // 直接下载
                that.pdf.save(title + '.pdf')
                that.isOver = true
            } else {
                // 在新窗口查看 pdf文件
                window.open(that.pdf.output('bloburl'))
                that.isOver = true
            }
            that.init();
        };
        const createImpl = async (canvas) => {
            console.log('这页PDF剩余的高度', state.a4LeftHeight)
            console.log('canvas剩余的高度', state.leftHeight)
            console.log('canvas开始截取的位置高度', state.position)
            if (state.leftHeight > 0) {
                if (state.leftHeight > state.a4LeftHeight) {
                    var checkCount = 0
                    var i = state.position + state.a4LeftHeight
                    // 从定好的高度页面,底部开始循环遍历canvas的每个点,找到可以截断的地方
                    for (i; i >= state.position; i--) {
                        var count = 0
                        var isWrite = true
                        for (var j = 0; j < canvas.width; j++) {
                            var c = canvas.getContext('2d').getImageData(j, i, 1, 1).data
                            // 如果该单位的颜色不是白色c[0]  c[1]  c[2] 分别代表r g b 255
                            if (c[0] != 0xff || c[1] != 0xff || c[2] != 0xff) {
                                count++
                            }
                            // 如果这行有连续20个单位都不是白色,退出当前循环
                            if (count > 20) {
                                isWrite = false
                                break
                            }
                        }
                        // 如果有连续10行都是白色的,canvas在这里可以截断了
                        if (isWrite) {
                            checkCount++
                            if (checkCount >= 20) {
                                break
                            }
                        } else {
                            checkCount = 0
                        }
                    }
                    state.height = i - state.position
                    if (state.height <= 0) { // 没找到截断点,新增一页PDF
                        // PDF剩余可用高度
                        state.a4LeftHeight = (state.a4HeightRef - 150).toFixed(2) / 1
                        // 先添加一张PDF
                        state.pdf.addPage()
                        state.pdfProgress = state.pdfProgress + 1
                        console.log('新增一页PDF  state.pdfProgress', state.pdfProgress)
                        state.height = state.leftHeight
                        createImpl(canvas)
                        return
                    }
                } else {
                    state.height = state.leftHeight
                }
                state.canvas1.width = canvas.width
                state.canvas1.height = state.height
                var ctx = state.canvas1.getContext('2d');
                ctx.drawImage(canvas, 0, state.position, canvas.width, state.height, 0, 0, canvas.width, state.height)
                console.log('canvas截断的位置', state.position, state.height)
                console.log('PDF生成的位置', state.a4HeightRef - state.a4LeftHeight, state.height)
                state.list.push(state.canvas1.toDataURL('image/jpeg', 1.0));
                state.pdf.addImage(state.canvas1.toDataURL('image/jpeg', 1.0), 'JPEG', 90, state.a4Width / state.canvas1.width * (state.a4HeightRef - state.a4LeftHeight)+26, state.a4Width, state.a4Width / state.canvas1.width * state.height)
                state.leftHeight -= state.height
                state.position += state.height
                state.a4LeftHeight -= state.height + 50
                if (state.leftHeight > 0) { // 第i个canvas还未截取完毕
                    await createImpl(canvas)
                    console.log(5555555555);
                }
            }
        };
        const addPage = async () => {
            // PDF页面剩余的高度
            state.a4LeftHeight = (state.a4HeightRef - 150).toFixed(2) / 1
        };
        const init = () => {
            state.pdf = null;
            state.canvas = [];
            state.isAddPage = false;
            state.pdfProgress = 1;
            state.pdfPage = 1;
            state.pdfTotal = null;
            state.canvas1 = null;
        }
        return {
            ...toRefs(state),
            getPdfFun,
        }
    }
    
    • 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
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
  • 相关阅读:
    Java中的ORM框架——myBatis
    [jetson][转载]jetson上安装pycharm
    面试题:如何正确的停掉线程?
    深度学习与CV教程(4) | 神经网络与反向传播
    CTF-Crypto学习记录-第三天 MD5加密算法(信息摘要算法)“ “
    Redis简易入门15招
    关于mac下pycharm旧版本没删除的情况下新版本2023安装之后闪退
    机器人仿真-SolidWorks学习笔记(0)-前期准备
    数据结构:顺序表的增删改查
    SpringBoot整合消息中间件(ActiveMQ,RabbitMQ,RocketMQ,Kafka)
  • 原文地址:https://blog.csdn.net/zsm4623/article/details/127755640