canvas2html 遇到的跨域问题

背景:
当我们出现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 遇到的跨域问题)