最近產品提出了一個需求:咱們在合做方的app中提供的部分頁面中增長分享頁面,具體要求是在3個二維碼推廣頁面調用app的分享接口,分享方式有3種,分別是點擊」分享連接「按鈕調起分享,點擊」分享圖片「按鈕調起分享,以及長按保存頁面。html
二維碼的推廣頁面是由一張背景圖和一張動態生成的二維碼圖片組成。前端
點擊」分享連接「調起分享很是簡單,就再也不贅述了。canvas
點擊」分享圖片「按鈕進行分享,合做方app接口要求傳入進行分享的圖片地址。這就要求分享出去的圖片先要存在圖片服務器中,可是每一個用戶的分享二維碼是不一樣的,咱們不可能爲每一個用戶畫一張分享圖片,再存到服務器中。通過一番搜索,最終決定由前端對分享頁面截圖,上傳服務器,再把返回的圖片地址傳給app。數組
前端截圖主要用到2個庫,html2canvas 和canvas2image。顧名思義,先把頁面元素輸出到canvas上,再把canvas轉成圖片上傳到服務器。服務器
function createPicture() { var shareButton = document.querySelector(".share-button"); // 獲取不但願出如今截圖中的DOM,而後隱藏,等圖片生成完畢,再恢復顯示 var tip = document.querySelector(".tip"); shareButton.style.display = "none"; tip.style.display = "none"; html2canvas(document.body).then(function (canvas) { var img = Canvas2Image.convertToPNG(canvas, canvas.width, canvas.height); var base64 = img.src; var byteString = atob(base64.split(",")[1]); //base64 解碼 var arrayBuffer = new ArrayBuffer(byteString.length); //建立緩衝數組 var intArray = new Uint8Array(arrayBuffer); //建立視圖 for (var i = 0; i < byteString.length; i++) { intArray[i] = byteString.charCodeAt(i); } var b = new Blob([intArray], {type: "image/png"}); b.lastModifiedDate = new Date(); b.name = Date.now() + ".png"; var file = new FormData(); file.append("upfile", b, b.name); shareButton.style.display = "flex"; tip.style.display = "flex"; return file; }); }// 函數返回一個文件對象,把文件對象上傳服務器便可
」長按保存「的原理也相似,首先背景圖和二維碼都須要是dom元素的background-image,由於移動端H5是沒有長按事件的,因此使用touch事件模擬。若是把把背景圖、二維碼圖設爲img標籤,再app也設定捕獲屏幕的長按事件的狀況下,H5頁面捕獲touch事件同時,app也會捕獲長按事件,形成調起2次事件處理。設爲background-image能夠避免app捕獲長按事件。長按保存的具體原理是,touchstart事件處理函數:調用setTimeout設定1-2秒後調用截圖函數並上傳服務器,並把返回的圖片地址傳給app,touchmove,touchend事件處理函數:使用clearTimeout取消定時器。這樣只有一直按着不動,通過預約的時間後,調起真正的時間處理函數,手指移動或者離開屏幕清除定時間,真正的事件處理函數不會執行。app