html2canvas截屏在H5微信移動端踩坑,ios和安卓均可顯示


1.最近在做移動端開發,框架是vue,一產品需求是,后台返回數據,通過qrcode.js(代碼比較簡單,百度上已經很多了)生成二維碼,然后通過html2canvas,將html元素轉化為canvas,通過 canvas.toDataURL() 方法轉化為base64,二進制流的圖片,顯示在頁面上,因為微信內置瀏覽器不支持下載(可能是我不會,誰實現了可以教一下我),需要用戶觸屏手動保存圖片。下面貼出部分代碼

 
2.
<template>
    <section id="section">
  <p>當前積分<span>365</span></p>
  <p>參與項目數量<span>12</span></p>
  <p>募捐金額<span>45678</span>元</p>
  <p>榮譽等級<span>海綿寶寶</span></p>
  <div id="qrcode">
  </div>
    </section>
    <div id='photo'>
  <span>長按圖片保存和分享</span>
    </div>
 <button @click="saveImg">生成圖片</button>
</template>
<script>
  export default{
    methods:{ 
      saveImg(){
        var shareContent = document.getElementById("section");
        html2canvas( shareContent,{
          onrendered: function(canvas){
          var img = new Image();
          img.src = canvas.toDataURL() ;
          document.getElementById("photo").appendChild(img);
          
        }
      })
    }
      }
</script>

 

3.當然前提是先引入html2canvas文件,我直接在index.html 引入CDN 地址是 
  
<script src="https://cdn.bootcss.com/html2canvas/0.4.1/html2canvas.js"></script>

 

不要問我為什么不用最新 0.5.0版本,網上有人說坑比較多,我項目趕進度,沒來得及去踩坑,你們想嘗試也可以玩玩。
 
4.然而,通過上述代碼,PC端,包括開發者工具均可顯示生成的圖片,移動端安卓系統也能正常顯示和保存。然而,坑坑的IOS圖片區域一片空白;於是,本人開始漫長的百度之旅
 
5.說法1:ios顯示base64圖片,需要去除格式前綴
 我們通過控制台,可以看到canvas.toDataURL() 出來的格式,img src 可以直接顯示 "data:image/png;base64,iVBORw0KGgoAAAANSU.....==="格式的圖片,但是ios需要去除 data:image/png;base64 前綴,於是我通過以下判定,當是IOS系統時,去除前綴
   
 var u = navigator.userAgent, app = navigator.appVersion;
    var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //g
    var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios終端
    if (isAndroid) {
      //這個是安卓操作系統
      mg.src = canvas.toDataURL() ;
    }
    if (isIOS) {
      //這個是ios操作系統
      mg.src = canvas.toDataURL() .replace("data:image/png;base64,","");
    }

 

 然而開發者工具調為IOS手機,也出現系統報錯,可以發現,去除前綴,瀏覽器會自動添加地址前綴。所以,這種解決辦法失敗。接着來

 

 
 
6.說法2,首先在頁面添加img,通過給src賦值,完成,而不是appendChild
  
 
<div id='photo'>
  <span>長按圖片保存和分享</span>
  <img src=""  id="img">
    </div>
  ..
  
  html2canvas( shareContent,{
    onrendered: function(canvas){
      document.getElementById("img").src = canvas.toDataURL() ;
    }
  }

 

  當然,結果依舊是空白一片 
 
7.說法3,無效
   
document.getElementById("img").src = canvas.toDataURL() .replace("image/png", "image/octet-stream") ;

 

 
8.說法4,blob格式生成http URL地址格式顯示
 和說法1有點相關,當去掉IMG格式前綴,SRC會添加域名,顯示地址,那我們直接顯示地址行不行,有人通過后台完成,但是,太過復雜。嘗試blob格式生成http URL?
  
function dataURLtoBlob(dataurl) {
    var arr = dataurl.split(','),mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while(n--){
      u8arr[n] = bstr.charCodeAt(n);
    }
      return new Blob([u8arr], {type:mime});
   }
  let dataUrl = dataURLtoBlob(canvas.toDataURL()) ;
 document.getElementById("img").src = URL.createObjectURL(dataUrl);

 


 這樣,IMG的SRC顯示就不是base64格式,而是http格式的URL,但是,ios依然無法顯示圖片

8.做到這里,我產生了讓后端幫助的念頭,但隨后放棄了,於是開始整理思路,我一直覺得是ios不支持base64格式圖片,網上也有人說是ios11無法顯示html2canvas.然而通過第四種借助http url的方法,還是沒有成功,於是我開始思考是不是其他地方出現的問題。搜索了很多文章,忽然一個說法讓我覺得很有可能是解決辦法,那就是,ios系統無法動態給img src賦值,可以通過div 顯示背景的方式顯示圖片。但是,即使可以成功,也完不成我這個項目功能,因為作為背景圖的話,用戶無法觸屏保存圖片...而,這里,就體現了框架相對原生JS的好處,我可以通過v-bind綁定src 再給data賦值的方式。激動的我趕緊嘗試。
<template>
    <section id="section">
  <p>當前積分<span>365</span></p>
  <p>參與項目數量<span>12</span></p>
  <p>募捐金額<span>45678</span>元</p>
  <p>榮譽等級<span>海綿寶寶</span></p>
  <div id="qrcode">
  </div>
    </section>
    <div id='photo'>
  <span>長按圖片保存和分享</span>
  <img :src="url">
    </div>
 <button @click="saveImg">生成圖片</button>
</template>
<script>
  export default{
    data(){
      return{
        url:""
      }
    },    
    methods:{ 
      saveImg(){
        var shareContent = document.getElementById("section");
        html2canvas( shareContent,{
          onrendered: function(canvas){
          this.url = canvas.toDataURL() ;        
        }
      })
    }
      }
</script>

 

 

大功告成!嗯...最后的原因只是因為ios不支持直接給img src賦值,

當然,還可以優化,比如加入截屏聲音。
 
 //添加快門聲音
  var audio = document.createElement("audio");
  audio.src = "/static/1374.wav";
  audio.autoplay = "autoplay" ;
  photo.appendChild(audio);
  setTimeout(()=>{
    photo.removeChild(audio);
  },2000);

 

 


免責聲明!

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



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