微信服務號分享圖片(包括微信頭像以及二維碼)

flyMusk發表於2018-12-16

      

     最近一個產品需要是把微信服務號中一個網頁內容生成一張圖片,使用者長按可以儲存為圖片,圖片中的二維碼可以識別,圖片中包含使用者頭像。效果如圖1-1

      最常用的做法是把網頁轉換為cancas,接著轉成圖片,最流行的外掛是html2canvas。官網的文件個人感覺不是特別好。html2canvas.hertzen.com/具體做法參考了此部落格。segmentfault.com/a/119000001…

  微信服務號分享圖片(包括微信頭像以及二維碼)

                                             圖1-1

  紅色圓圈位置應該為微信頭像的位置,web端獲取不到用紅圈代替。右下角二維碼是根據後端資料渲染出來的動態二維碼。

  整個需求難點和坑分為幾部分:

1.獲取頭像並且可以儲存到canvas生成的img中(canvas對於跨域圖片的處理一般是在原圖片處顯示空白---需要後端配合)

2.生成canvas比生成二維碼或微信頭像快,導致二維碼沒有附在canvas生成的整圖中(非同步處理,安排事件執行順序)

3.設定canvas寬高為背景大圖帶小數的原始尺寸(通過offsetWidth width等獲得的是取整之後的寬度 )以及偏移尺寸。

4.圖片清晰度處理(設定canvas畫布縮放比)


1.處理canvas中跨域的問題,微信頭像和自己的伺服器必然不在同一個域,那首先需要前端設定canvas的配置項,允許跨域。網上有幾種做法可以參考

1.1將微信頭像上傳到自己伺服器,再返回前段圖片地址,就不會涉及跨域問題。

1.2在NGINX上設定反向代理,把微信頭像域名地址換成自己伺服器的。(但是一旦微信頭像更新域名這種做法就會出bug )參考資料blog.csdn.net/mengruobaob…

location ^~ /wechat_image/ {
  add_header 'Access-Control-Allow-Origin' "$http_origin" always;
  add_header 'Access-Control-Allow-Credentials' 'true' always;
  add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always;
  add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-   Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;
  proxy_pass http://wx.qlogo.cn/;
}
複製程式碼

然後將微信的頭像 wx.qlogo.cn/xxx => https://${自己的域名}/wechat_image/xxx和後端協商好下劃線部分。

2.非同步處理可以涉及很多內容,筆者自己也不是特別懂,此處不展開講,下次專門出一篇非同步的部落格。此處處理將替換頭像地址,生成動態二維碼,canvas繪圖按照前中後三步順序執行,(沒有做非同步處理時,safiri中生成canvas比生成頭像和生成二維碼都快,導致最後的整圖沒有微信頭像和二維碼。)

3.生成canvas過程中會發現二維碼的位置會在開啟頁面一秒左右往上方偏移一下,一開始以為是因為生成的畫布以及圖片和之前的dom節點高度不同,所以設定了畫布高度時採用了getBoundingClientRect()獲得實際dom元素寬高,以及生成畫布過程中可能出現的偏移。

4.設定canvas的縮放scale。

程式碼如下:

 // $(function() {    
       function imgUrlChange(){    
            var wximg = $("#wximg").attr('src');      
           if(wximg){           
               var newimg =  window.location.origin +'/wechat_image'+ wximg.split("http://thirdwx.qlogo.cn")[1];    
            }else{     
               console.log('微信頭像沒有讀取到');      
             }     
           $("#wximg").attr('src',newimg);   
      }   
  function  shareQRCode () {    
    return new Promise (function(resolve,reject){   
        setTimeout(function() {      
          var  shareid = $("#urldata").attr('uid');   
            var qrcode = new QRCode('qrcode', {  
                  text: 'your content',
                   width: 90, 
                   height: 90,  
                  correctLevel: QRCode.CorrectLevel.H  
              });             
   //使用 API           
     qrcode.clear();      
     qrcode.makeCode(shareid);  
     console.log(2);       
     resolve();        
    },0)      
   })  
 }    
  function canvasImg (){    
    console.log(3)     
  setTimeout(function(){        
    var cntElem = $('#html2canvas')[0];   
         var shareContent = cntElem;//需要截圖的包裹的(原生的)DOM 物件 
         var cont = cntElem.getBoundingClientRect(); 
         var width = cont.width; //獲取dom 寬度  
         var height = cont.height; //獲取dom 高度 
         var canvas = document.createElement("canvas"); //建立一個canvas節點
         var scale = 2; //定義任意放大倍數 支援小數     
         canvas.width = width * scale; //定義canvas 寬度 * 縮放  
         canvas.height = height * scale; //定義canvas高度 *縮放  
         var context = canvas.getContext("2d");    
         context.scale(scale, scale); //獲取context,設定scale
         context.translate(-cont.left,-cont.top);//設定context位置,值為相對於視窗的偏移量負值,讓圖片復位       
         var opts = {       
            scale: scale, // 新增的scale 引數
            canvas: canvas, //自定義 canvas  
            // logging: true, //日誌開關,便於檢視html2canvas的內部執行流程  
            width: width, //dom 原始寬度          
            height: height,              
            useCORS: true // 【重要】開啟跨域配置       
     };           
  html2canvas(shareContent, opts).then(function (canvas) {  
              // 【重要】關閉抗鋸齒      
          context.mozImageSmoothingEnabled = false; 
          context.webkitImageSmoothingEnabled = false;  
          context.msImageSmoothingEnabled = false;  
          context.imageSmoothingEnabled = false;   
           // 【重要】預設轉化的格式為png,也可設定為其他格式    
          var image = canvas.toDataURL("image/png");          
          var pHtml = "<img src="+image+" />";          
          $('#html2canvas').html(pHtml);             
          $('#html2canvas>img').css({                
              "width": 100 + "%",                
               "height":height,             
       });            
    }, 200)             
  });   
}      
   imgUrlChange()   
   shareQRCode().then(function() { canvasImg() }) // })複製程式碼



相關文章