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

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

 
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手機,也出現系統報錯,能夠發現,去除前綴,瀏覽器會自動添加地址前綴。因此,這種解決辦法失敗。接着來html

 

 
 
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);
相關文章
相關標籤/搜索