上次分享的通过php方式生成的海报图片总有写字是模糊的,多次调试没有解决问题,后来干脆想办法在前端页面直接搞,请教了前端的大佬后分享了一个
很不错的js脚本,可以快速实现html转换成canvas画布,然后自行通过其他逻辑下载截图即可。
效果图:
html2canvas.js引入到项目进行操作即可,可以对指定的元素进行“截图”模式。
特别注意:图片千万不要用background方式设置,否则会模糊,之前用span的background设置图片,发现很模糊,经过查阅资料发现用img标签替代就行了,这样才很清晰。
案例代码(自己非专业前端,不喜勿喷,基于weui排版写的页面):
<!doctype html> <html> <head> <meta charset="utf-8"> <title>海报分享</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="/static/weui/css/weui.css"> <link rel="stylesheet" href="/static/weui/css/weuix.css"> <style> .info-text{ width: 70%; float: left; } .info-img{ width: 30%; float: right; line-height: 100%; } .info-img img{ max-height: 100%; max-width: 100%; } .info-img .qrcode{ width: 100%; } #content{ margin:0 auto; max-width: 650px; } .tip{ font-size: 18px; text-align: center; padding: 10px; font-weight: bold; } </style> </head> <body ontouchstart> <div> <div id="content"> <ul> <li style="width: 100%"> <img src="/upload/test/share/1.jpg" style="max-width: 100%;"/> </li> <li style="width: 100%;background: white;overflow: hidden;padding: 10px"> <div> <b style="overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;">正宗初生蛋小个头40枚10枚散养农村散养初生鸡蛋现捡新鲜鸡蛋批发</b> <br> ¥ <b style="color: red">27.9</b> <div style="color: grey;font-size: 14px">识别右侧的二维码进入了解详情</div> </div> <div> <img src="/upload/test/share/qc.png" alt=""> </div> <div style="clear: both"></div> </li> <li> <img src="/upload/test/share/1.jpg" style="max-width:100%"/> </li> <li> <img src="/upload/test/share/6.jpg" style="max-width:100%"/> </li> <li> <img src="/upload/test/share/2.jpg" style="max-width:100%"/> </li> <li> <img src="/upload/test/share/3.jpg" style="max-width:100%"/> </li> <li> <img src="/upload/test/share/4.jpg" style="max-width:100%"/> </li> <li> <img src="/upload/test/share/5.jpg" style="max-width:100%"/> </li> </ul> </div> <div></div> <div> <p class="f-red tip">请长按图片保存到本地并分享</p> </div> </div> <br> <br> <script src="/static/weui/js/zepto.min.js"></script> <script src="/static/weui/js/zepto.weui.js"></script> <script type="text/javascript" src="/static/js/html2canvas.min.js"></script> <script type="text/javascript"> //用JavaScript将画布保持成图片格式 function convertCanvasToImage(canvas) { var image = new Image(); image.src = canvas.toDataURL("image/png"); return image; } $.showLoading(); var c = document.getElementById("content") var options = { dpi: 300, scale: 2, // 添加的scale 参数 // width:500, useCORS: true // 【重要】开启跨域配置 }; html2canvas(c,options).then(function(canvas) { //$(".res").html(canvas) $(c).html("<img src='"+canvas.toDataURL('image/png')+"' style='max-width: 100%'/>") /*var a = document.createElement('a') //a.href = canvas.toDataURL('image/png') // 将画布内的信息导出为png图片数据 // a.download = '分享图片' // 设定下载名称 //a.className='weui-btn weui-btn-area weui-btn_primary' // a.innerHTML='保存海报' $(".btn").html(a)*/ }); $.hideLoading(); </script> </body> </html>
html2canvas的参数 http://html2canvas.hertzen.com/configuration:
调整js代码,设置scale比例,并自动下载为png:
var c = document.getElementById("content") var options = { scale:1.3,//按比例缩放 dip:2000,//没有发现有用 } html2canvas(c,options).then(function(canvas) { $(c).html(canvas) var a = document.createElement('a') a.href = canvas.toDataURL('image/png') // 将画布内的信息导出为png图片数据 a.download = '分享图片' // 设定下载名称 a.click() // 点击触发下载 });
另外,分享两个画布和图片互转的函数(或许有用哦):
//用JavaScript将画布保持成图片格式 function convertCanvasToImage(canvas) { var image = new Image(); image.src = canvas.toDataURL("image/png"); return image; } //使用JavaScript将图片拷贝进画布 function convertImageToCanvas(image) { var canvas = document.createElement("canvas"); canvas.width = image.width; canvas.height = image.height; canvas.getContext("2d").drawImage(image, 0, 0); return canvas; }
遇到的坑和解决方案:
问题1:图片跨域问题,比如拉取第三方平台的图片无法加载
解决:搭建本地图片资源转发服务,这里我用timthumb.php做,可以看这篇文章 如何在PHP中动态调整图像大小?今天分享这个小小的timthumb.php满足你的需求
问题2:图片截图显示不完整问题,滚动到下面开始截图时顶部空白
解决:页面加载完成后开始截图设置回到最顶部:document.body.scrollTop = document.documentElement.scrollTop = 0;
问题3:在移动端无法显示图片的问题,导致小图都不显示
解决:还是跨域问题,移动端和web端不一样,给图片添加匿名跨域属性:crossorigin="anonymous" 并设置useCORS: true // 【重要】开启跨域配置(不需要设置allowTaint: true,//允许跨域图片),然后就解决了。
问题4:进入页面直接生成的方式还是没有完整截图,经常只有部分
解决:进入页面后等页面加载完成设置一个延迟渲染,比如1秒:
setTimeout(function (){ start(); },1000)
问题5:图片过大也会导致生成画布不完整
解决:还是通过图片代理,重新设置图片的大小
优化后完整版:
<!doctype html> <html lang="zh"> <head> <meta charset="utf-8"> <title>海报分享</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="/static/weui/css/weui.css"> <link rel="stylesheet" href="/static/weui/css/weuix.css"> <style> .info-text { width: 70%; float: left; } .info-img { width: 30%; float: right; line-height: 100%; } .info-img img { max-height: 100%; max-width: 100%; } .info-img .qrcode { width: 100%; } #content { margin: 0 auto; max-width: 800px; /*border: 2px chartreuse dashed;*/ } .tip { font-size: 18px; text-align: center; padding: 10px; font-weight: bold; } img.s-img { height: 121px; } .weui-panel { background-color: #FFFFFF; margin-top: 10px; position: unset; overflow: hidden; /* bottom: 0; */ text-align: center; } </style> </head> <body ontouchstart> <div class="page-bd-15"> <div class="weui-feeds" id="content"> <ul> <li style="width: 100%;text-align: center"> <img src="https://source.alipay168.cn/wxauth.alipay168.cn/mstore/1f0e3dad99908345f7439f8ffabdffc4.png?v=1584009797" style="max-width:100%" /> </li> <li style="width: 100%;background: white;overflow: hidden;padding: 10px;max-width: 100%"> <div class="info-text"> <b style="overflow: hidden;text-overflow: ellipsis; display: -webkit-box;-webkit-line-clamp: 2;-webkit-box-orient: vertical;">爆款格蒙网红7天迷你口红套装多色一盒持久不脱色国货彩妆</b> <br> ¥ <b style="color: red">28.99</b> <div style="color: grey;font-size: 14px">识别右侧的二维码进入了解详情</div> </div> <div class="info-img"> <img class="qrcode" src="http://wei.test.top/upload/mstore/poster/qrcode/19_1f0e3dad99908345f7439f8ffabdffc4.png" alt=""> </div> <div style="clear: both"></div> </li> <li style="text-align: center"> <img alt="" crossorigin="anonymous" class="s-img" src="http://wei.test.top/index/tools/timg.html?src=http://wxauth.alipay168.cn/ueditor/php/upload/image/20200312/1584009531198704.jpg&w=121&q=100" style="max-width:100%"/> </li> <li style="text-align: center"> <img alt="" crossorigin="anonymous" class="s-img" src="http://wei.test.top/index/tools/timg.html?src=http://wxauth.alipay168.cn/ueditor/php/upload/image/20200312/1584009532970739.jpg&w=121&q=100" style="max-width:100%"/> </li> <li style="text-align: center"> <img alt="" crossorigin="anonymous" class="s-img" src="http://wei.test.top/index/tools/timg.html?src=http://wxauth.alipay168.cn/ueditor/php/upload/image/20200312/1584009532388616.jpg&w=121&q=100" style="max-width:100%"/> </li> <li style="text-align: center"> <img alt="" crossorigin="anonymous" class="s-img" src="http://wei.test.top/index/tools/timg.html?src=http://wxauth.alipay168.cn/ueditor/php/upload/image/20200312/1584009532120428.jpg&w=121&q=100" style="max-width:100%"/> </li> <li style="text-align: center"> <img alt="" crossorigin="anonymous" class="s-img" src="http://wei.test.top/index/tools/timg.html?src=http://wxauth.alipay168.cn/ueditor/php/upload/image/20200312/1584009533453186.jpg&w=121&q=100" style="max-width:100%"/> </li> <li style="text-align: center"> <img alt="" crossorigin="anonymous" class="s-img" src="http://wei.test.top/index/tools/timg.html?src=http://wxauth.alipay168.cn/ueditor/php/upload/image/20200312/1584009533432512.jpg&w=121&q=100" style="max-width:100%"/> </li> </ul> </div> <div class="res"></div> <div class="weui-panel" > <p class="f-red tip">请长按图片保存到本地并分享</p> </div> </div> <br> <br> <script src="/static/weui/js/zepto.min.js"></script> <script src="/static/weui/js/zepto.weui.js"></script> <script type="text/javascript" src="/static/js/html2canvas.min.js"></script> <script type="text/javascript"> function start(){ //先跳到最顶端(如果有操作按钮在底部的特别重要) document.body.scrollTop = document.documentElement.scrollTop = 0; var c = document.getElementById("content") var options = { dpi: 300, scale: 2, // 添加的scale 参数 //width:500, //height:1000, async:true,//是否异步 onclone:function(){ $.showLoading('海报生成中...'); }, proxy:null,//Url到 代理 ,用于加载跨源图像。如果留空,则不会加载跨原始图像。 imageTimeout:10000,//加载图像的超时(以毫秒为单位,设置 0 为禁用超时 // allowTaint: true,//允许跨域图片 taintTest: false,//是否在渲染前测试图片 useCORS: true // 【重要】开启跨域配置 }; html2canvas(c,options).then(function(canvas) { $.hideLoading(); $(c).html("<img src='"+canvas.toDataURL('image/png')+"' style='max-width: 100%'/>"); /*var a = document.createElement('a') a.href = canvas.toDataURL('image/png') // 将画布内的信息导出为png图片数据 a.download = '分享图片' // 设定下载名称 a.className='weui-btn weui-btn-area weui-btn_primary' a.innerHTML='保存海报' $(".btn").html(a)*/ }); } //用JavaScript将画布保持成图片格式 function convertCanvasToImage(canvas) { var image = new Image(); image.src = canvas.toDataURL("image/png"); return image; } $(function (){ setTimeout(function (){ start(); },1000) }) </script> </body> </html>
效果: