应用场景
生成带二维码的推广海报图片
旧方法
将用户自己的推广连接先通过qrcode.js生成二维码,然后再用后台返回的一张背景图片和二维码通过canvas绘制成一张海报。
问题
在部分安卓手机上获取二维码图片后,onload事件不起作用,代码演示如下。
<!---放二维码---> <div id="imgs" style="width:100px; height:100px; margin-top:15px;"hidden></div> <!-- 生成canvas海报 --> <canvas id="myCanvas" width="" height=""></canvas> <!-- 生成canvas海报 --> <!--海报弹窗--> <div class="shadow" onclick="shareHide()"></div> <img class="shareImg" id="imgShow" src=""> <script type="text/javascript"> document.onreadystatechange = loadingChange; // 当页面加载状态改变的时候执行这个方法. function loadingChange() { if(document.readyState == "Loading") { // 当页面加载状态为完全结束时进入 // $(".shodowS").show() } if(document.readyState == "complete") { // 当页面加载状态为完全结束时进入 var qrcodes = new QRCode(document.getElementById("imgs"), { width : 160, height : 160 }); qrcodes.makeCode('{$url}'); // 生成二维码 shareImgs(); } } var canvas = document.getElementById('myCanvas'); canvas.width=$("#container").width()*2; canvas.height=$("#container").width()*1440/1080*2; $("#myCanvas").css("width",$("#container").width()); $("#myCanvas").css("height",$("#container").width()*1440/1080); // 分享图片生成的 function shareImgs() { var qrcode=document.getElementById("imgss"); if (canvas.getContext) { var ctx = canvas.getContext('2d'); //创建新的图片对象 var img = document.getElementById("imgs1"); var img = new Image; //指定图片的URL // img.crossOrigin="anonymous"; // 这个可以对苹果手机做兼容(跨域) // img.src=img.src; img.src='{$bg[0]}'; img.onload = function() { var imgOw=img.width,imgOh=img.height; var imgW=canvas.width,imgH=(imgOh*canvas.width)/imgOw; var imgX=0,imgY=0; //以Canvas画布上的坐标(10,10)为起始点,绘制图像 ctx.drawImage(img, imgX, imgY,imgW,imgH); var qrcodeX, qrcodeY,qrcodeW,qrcodeH; qrcode.crossOrigin="anonymous"; qrcode.src=qrcode.src; qrcode.onload = function() { //以Canvas画布上的坐标(10,10)为起始点,绘制图像 ctx.drawImage(qrcode,846/1080*canvas.width, 1220/1440*(imgOh*canvas.width)/imgOw+(canvas.height-imgH)/2, 160/1440*img.width, 160/1440*img.width); var _imgSrc = canvas.toDataURL("image/png",1); var imgShow = document.getElementById('imgShow'); imgShow.setAttribute('src', _imgSrc); } } } } </script>
解决方法
虽然知道是页面渲染的先后问题,但是时间很紧,只能跳过使用另一种方式解决这种在有的手机上不能生成海报的问题。所以决定通过后台生成二维码放在页面,然后JS只需要获取后台返回的base64二维码和海报绘制再生成图片,最后安卓苹果手机都能显示了。
1. 使用的是phpqrcode类,不过需要简单的修改一下,让其能生成base64的二维码,这个我是在网上参考别人的源码,具体是谁忘记了,记起后代码原著我会补上,这里就代码先上了。
2. PHP后台生成并返回
/*生成二维码**/ //打开缓冲区 ob_start(); //生成二维码图片 $returnData = QRcode::pngString($url,false, "H", 3, 1); //这里就是把生成的图片流从缓冲区保存到内存对象上,使用base64_encode变成编码字符串,通过json返回给页面。 $imageString = base64_encode(ob_get_contents()); //关闭缓冲区 ob_end_clean(); $shareQrcode = "data:image/png;base64,".$imageString; /**生成二维码*/
3. 前端显示二维码,并js获取重新绘制
<!-- 二维码图片 --> <img src="{$bg[0]}" hidden="hidden" id="imgs1"> <!--PHP生成的二维码--> <img src="{$shareQrcode}" hidden="hidden" id="phpQrcodeImg"> <script type="text/javascript"> var canvas = document.getElementById('myCanvas'); canvas.width=$("#container").width()*2; canvas.height=$("#container").width()*1440/1080*2; $("#myCanvas").css("width",$("#container").width()); $("#myCanvas").css("height",$("#container").width()*1440/1080); // 分享图片生成的 function shareImgs() { var qrcode=document.getElementById("imgss"); var testQrcode = document.getElementById("phpQrcodeImg"); if (canvas.getContext) { var ctx = canvas.getContext('2d'); //创建新的图片对象 var img = document.getElementById("imgs1"); var img = new Image; img.src='{$bg[0]}'; img.onload = function() { var imgOw=img.width,imgOh=img.height; var imgW=canvas.width,imgH=(imgOh*canvas.width)/imgOw; var imgX=0,imgY=0; //以Canvas画布上的坐标(10,10)为起始点,绘制图像 ctx.drawImage(img, imgX, imgY,imgW,imgH); // js生成二维码在部分安卓机上无法获取到二维码图片资源最后onload不到 var qrcodeX, qrcodeY,qrcodeW,qrcodeH; qrcode.crossOrigin="anonymous"; qrcode.src=qrcode.src; // 修改为PHP生成的二维码 testQrcode.crossOrigin="anonymous"; testQrcode.src = testQrcode.src; testQrcode.onload = function() { //以Canvas画布上的坐标(10,10)为起始点,绘制图像 ctx.drawImage(testQrcode,846/1080*canvas.width, 1220/1440*(imgOh*canvas.width)/imgOw+(canvas.height-imgH)/2, 160/1440*img.width, 160/1440*img.width); var _imgSrc = canvas.toDataURL("image/png",1); // canvas.style.display="none"; var imgShow = document.getElementById('imgShow'); imgShow.setAttribute('src', _imgSrc); } } } } </script>