解決vue中html2canvas圖片跨域問題


HTML代碼

<div id="pdfDom" >
 
</div>

<script>

import htmlToPdf from '@/components/utils/htmlToPdf' //頁面打印

export default {
  methods: {
 
    gethtmlToPdf(){
    var title = 'tttt';//PDF的文件名

    htmlToPdf.downloadPdf(title)

    },

  }
}

</script>

PDF打印插件

src/components/utils/htmlToPdf.js

//該部分代碼是從網上找的,然后根據我自己的需求,調試修改得來。

//本人系后端開發,前端接手不久,所以部分代碼都是百度得來,請見諒。

// 導出頁面為PDF格式
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default{
  //有分頁
  getPdf(name){
    window.pageYoffset = 0;
    document.documentElement.scrollTop = 0;
    document.body.scrollTop = 0;

    let shareContent = document.querySelector('#pdfDom'),//需要截圖的包裹的(原生的)DOM 對象
      width = shareContent.clientWidth, //獲取dom 寬度
      height = shareContent.clientHeight, //獲取dom 高度
      // height = canvas.height, //獲取dom 高度
      canvas = document.createElement("canvas"), //創建一個canvas節點
      scale = 1.5; //定義任意放大倍數 支持小數

    html2Canvas(shareContent, {
      allowTaint: true,
      // scale: scale, // 添加的scale 參數
      // canvas: canvas, //自定義 canvas
      logging: false, //日志開關,便於查看html2canvas的內部執行流程
      // width: width, //dom 原始寬度
      // height: height,
      useCORS: true, // 【重要】開啟跨域配置
      scale : 1.5
    }).then(function (canvas) {
        let contentWidth = canvas.width
        let contentHeight = canvas.height
        let pageHeight = contentWidth / 592.28 * 841.89
        let leftHeight = contentHeight
        let position = 0
        let imgWidth = 595.28
        let imgHeight = 592.28 / contentWidth * contentHeight
      //設置圖片跨域訪問
      //   img.setAttribute('crossOrigin', 'anonymous');
        let pageData = canvas.toDataURL('image/jpeg', 1.0)
        let PDF = new JsPDF('', 'pt', 'a4')
        if (leftHeight < pageHeight) {
          PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
        } else {
          while (leftHeight > 0) {
            PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
            leftHeight -= pageHeight
            position -= 841.89
            if (leftHeight > 0) {
              PDF.addPage()
            }
          }
        }
        PDF.save(name + '.pdf')
      }
    )
  },

  //test -- 無分頁
  downloadPdf(name) {
    window.pageYoffset = 0;
    document.documentElement.scrollTop = 0;
    document.body.scrollTop = 0;

    let shareContent = document.querySelector('#pdfDom'),//需要截圖的包裹的(原生的)DOM 對象
      width = shareContent.clientWidth, //獲取dom 寬度
      height = shareContent.clientHeight, //獲取dom 高度
      // height = canvas.height, //獲取dom 高度
      canvas = document.createElement("canvas"), //創建一個canvas節點
      scale = 1.5; //定義任意放大倍數 支持小數

    // console.log(tt)
    setTimeout(() => {
      html2Canvas(shareContent, {
        // allowTaint: false,這部分,最好還是不用,原因是,容易污染畫布。
        scale: 2.5, // 提升畫面質量,但是會增加文件大小
        useCORS: true, // 【重要】開啟跨域配置
        backgroundColor: "#fff", // 一定要添加背景顏色,否則出來的圖片,背景全部都是透明的
        // foreignObjectRendering: true,
      }).then(function (canvas) {
        /**jspdf將html轉為pdf一頁顯示不截斷,整體思路:
         * 1. 獲取DOM
         * 2. 將DOM轉換為canvas
         * 3. 獲取canvas的寬度、高度(稍微大一點)
         * 4. 將pdf的寬高設置為canvas的寬高
         * 5. 將canvas轉為圖片
         * 6. 實例化jspdf,將內容圖片放在pdf中(因為內容寬高和pdf寬高一樣,就只需要一頁,也防止內容截斷問題)
         */

          // 得到canvas畫布的單位是px 像素單位
        var contentWidth = canvas.width
        var contentHeight = canvas.height

        // 將canvas轉為base64圖片
        var pageData = canvas.toDataURL('image/jpeg', 1.0)

        // 設置pdf的尺寸,pdf要使用pt單位 已知 1pt/1px = 0.75   pt = (px/scale)* 0.75
        // 2為上面的scale 縮放了2倍
        var pdfX = (contentWidth + 10) / 2 * 0.75
        var pdfY = (contentHeight + 10) / 2 * 0.75  // 10為底部留白

        // 設置內容圖片的尺寸,img是pt單位
        var imgX = pdfX;
        var imgY = (contentHeight / 2 * 0.75); //內容圖片這里不需要留白的距離

        // 初始化jspdf 第一個參數方向:默認''時為縱向,第二個參數設置pdf內容圖片使用的長度單位為pt,第三個參數為PDF的大小,單位是pt
        var PDF = new JsPDF('', 'pt', [pdfX, pdfY])

        // 將內容圖片添加到pdf中,因為內容寬高和pdf寬高一樣,就只需要一頁,位置就是 0,0
        PDF.addImage(pageData, 'jpeg', 0, 0, imgX, imgY)
        PDF.save(name+'.pdf')
      })
    }, 200);
  },

}

以上代碼,雖然可以打印成PDF,但是,如果頁面中有引入外鏈的圖片,入OSS上的圖片,往往會出現跨域的問題。

具體原因見下鏈接 這里 這是一個我覺得寫得相對比較詳細的文章

 

 后來做了各種嘗試,找到了一個解決辦法

修改HTML里的代碼

gethtmlToPdf
<div id="pdfDom" >
 
</div>

<script>
import htmlToPdf from '@/components/utils/htmlToPdf' //頁面打印

export default {
  methods: {
    
    
gethtmlToPdf(){
var title = this.$route.query.billNumber
let shareContent = document.querySelector('#pdfDom'); //定義任意放大倍數 支持小數

let imgList = shareContent.querySelectorAll('img')
if (imgList){
var i;
for (i = 1; i < imgList.length; i++) {

imgList[i].src += '&timeSign='+Date.now().toString()
console.log(imgList[i].src)

window.URL = window.URL || window.webkitURL;
var xhr = new XMLHttpRequest();
xhr.open("get", imgList[i].src, true);
xhr.send();
}
}
// console.log(1)
htmlToPdf.downloadPdf(title)

},
   } } </script>

如此即可,按我的理解,應該是此部分代碼會重新打開一次圖片,然后會直接刷新緩存中的連接,使其信息得以保全,所以在此訪問不會出現跨域問題。

本人較懶,且前端專業知識不足,如果有大佬能夠更詳細的解釋,請留下鏈接,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM