美文网首页
canvas2html 遇到的跨域问题

canvas2html 遇到的跨域问题

作者: 佳瑞Jarrett | 来源:发表于2021-09-05 13:48 被阅读0次

    背景:
    当我们出现vue页面需要保存为pdf文件时,网络上提供的办法几乎都是如下。
    使用html2canvas 以及jspdf 两个库。

    // 导出页面为PDF格式
    
    import html2canvas from 'html2canvas'
    import JSPDF from 'jspdf'
    
    export default {
        install(Vue, options) {
            Vue.prototype.ExportSavePdf = function (htmlTitle, currentTime) {
                var element = document.getElementById('pdfContent')
                html2canvas(element, {
                    logging: false
                }).then(function (canvas) {
                    var pdf = new JSPDF('p', 'mm', 'a4') // A4纸,纵向
                    var ctx = canvas.getContext('2d')
                    var a4w = 170;
                    var a4h = 257 // A4大小,210mm x 297mm,四边各保留20mm的边距,显示区域170x257
                    var imgHeight = Math.floor(a4h * canvas.width / a4w) // 按A4显示比例换算一页图像的像素高度
                    var renderedHeight = 0
                    while (renderedHeight < canvas.height) {
                        var page = document.createElement('canvas')
                        page.width = canvas.width
                        page.height = Math.min(imgHeight, canvas.height - renderedHeight) // 可能内容不足一页
                        // 用getImageData剪裁指定区域,并画到前面创建的canvas对象中
                        page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0)
                        pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width)) // 添加图像到页面,保留10mm边距
                        renderedHeight += imgHeight
                        if (renderedHeight < canvas.height) {
                            pdf.addPage()
                        } // 如果后面还有内容,添加一个空页
                        // delete page;
                    }
                    pdf.save(htmlTitle + currentTime)
                })
            }
        }
    }
    
    • 这段代码的原理是首先创建canvas对象,然后利用 ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)按照设定的长宽尺度将页面保存为图片,最后将保存的图片塞到pdf文档中。
    • 该方法对于常规页面来说,都可以很好的保存下来。但是无法很好的支持某些dom分段分页,因为它是按照长宽尺寸进行裁剪的,无法对表格图片等很好的识别进行分段保存。而且保存下来的文字等信息是无法选中的,产生的原因同样是保存下来的文档里其实都是图片。

    产生了新的问题

    在我的页面中引用了第三方的图片地址,而且这些第三方图片是不固定的。再到处这些图片为dpf时,总是会出现如下问题:

    Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data. 
    

    问题原因

    在网页的html中引入第三方的图片,导致出现了无法截图的问题。

    解决问题

    使用浏览器自带的打印功能,将页面保存为pdf。相比于原来需要解决跨域问题,该种方法不需要进行设置;但该方法每次在导出pdf的时候,需要进行预览后保存;保存下来的文字图片是可以被选中的;页面中会出现一些附属信息,例如网址,日期,页码等;页面同样对表格、图片等无法做到很好的分段分页等。

    // 1.设置要打印的区域 div的className
    var newstr = document.getElementsByClassName('printOrder-data')[0].innerHTML
    // 2. 复制给body,并执行window.print打印功能
    document.body.innerHTML = newstr
    // 3. 还原:将旧的页面储存起来,当打印完成后返给给页面。
    var oldstr = document.body.innerHTML
    window.print()
    document.body.innerHTML = oldstr
    

    总结

    各种方法有利有弊,需要结合业务的实际情况,做出一些调整。

    如果您觉得上面的内容对您有帮助欢迎点赞、评论、转发!
    更多内容请查阅作者博客:https://jiaruiblog.com
    或者star作者github: https://github.com/Jarrettluo?tab=repositories

    相关文章

      网友评论

          本文标题:canvas2html 遇到的跨域问题

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