最近产品提出了一个需求:咱们在合做方的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