最近產品提出了一個需求:我們在合作方的app中提供的部分頁面中增加分享頁面,具體要求是在3個二維碼推廣頁面調用app的分享接口,分享方式有3種,分別是點擊”分享鏈接“按鈕調起分享,點擊”分享圖片“按鈕調起分享,以及長按保存頁面。
二維碼的推廣頁面是由一張背景圖和一張動態生成的二維碼圖片組成。
點擊”分享鏈接“調起分享非常簡單,就不再贅述了。
點擊”分享圖片“按鈕進行分享,合作方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取消定時器。這樣只有一直按着不動,經過預定的時間后,調起真正的時間處理函數,手指移動或者離開屏幕清除定時間,真正的事件處理函數不會執行。