在工作中偶尔会遇到绘制转发卡/邀请卡的业务,且这个转发卡/邀请卡的风格会有很多,要求最后生成图片。这时候如果使用一张图片绘制一个canvas,这个工作量会相当大。分析一下转发邀请的内容,会发现所有的里面的元素都是一样的,只是风格不一致,所以我使用了解析json结构来绘制canvas,如果后期需要增加风格,只要增加json就可以了。
demo图大概这样:
点击下方的不同风格的图片就会生成不一样的图片。
下面我们要实现代码:
style样式:
*{padding: 0;margin: 0;}body{width: 100%;height:100%;overflow: hidden;}.ul{ position: fixed;bottom: 0;display: flex;width: 100%;font-size: 0;text-align: center; }a{height: 1.2rem;flex: 1;font-size: 14px;margin: 0 .1rem .1rem; }img{ width: 100%;height: 100%; }.temp{ width:100%;height: 10rem;margin: 0 auto;}
html结构:
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" /><title>canvas+json实现方法</title></head><body><div class="main"> <div class="temp"><canvas id="canvas"></canvas></div><div class="ul"><a href="javascript:drawPic(1)"><img src="images/1.jpg"></a><a href="javascript:drawPic(2)"><img src="images/2.jpg"></a><a href="javascript:drawPic(3)"><img src="images/3.jpg"></a><a href="javascript:drawPic(4)"><img src="images/4.jpg"></a></ul></div> <script src="jquery-3.2.1.min.js"></script><script src="demo.js"></script></body></html>
demo.js:
// 适应各种屏幕尺寸;(function(win) { ???var doc = win.document; ???var docEl = doc.documentElement; ???var tid; ???function refreshRem() { ???????var width = docEl.getBoundingClientRect().width; ???????if (width > 640) { // 最大宽度 ???????????width = 640; ???????} ???????var rem = width / 6.4; ????????docEl.style.fontSize = rem + ‘px‘; ???} ???win.addEventListener(‘resize‘, function() { ???????clearTimeout(tid); ???????tid = setTimeout(refreshRem, 300); ???}, false); ???win.addEventListener(‘pageshow‘, function(e) { ???????if (e.persisted) { ???????????clearTimeout(tid); ???????????tid = setTimeout(refreshRem, 300); ???????} ???}, false); ???refreshRem();})(window);// 不同风格的json结构,在实际业务中可以移到服务器中var json={"success":true,"msg":null,"code":1,"lists":[{"id":1,"bgcolor":"rgb(0,0,0)","url":"./images/1.jpg","elements":[ ??//存放元素{"type":"img","url":"./images/user.jpg","style":{"width":80,"height":80,"left":20,"top":20,"border":0,"borderRadius":100 //100表示画原形图片 0表示矩形图片 0-100表示圆角图片}},{"type":"txt","content":"何小姐的博客","style":{"color":"#fff","left":115,"top":55,"fontsize":20,"fontfamily":"Microsoft Yahei","textalign":"left",}},{"type":"txt","content":"http://www.cnblogs.com/heyujun-/","style":{"color":"#fff","left":115,"top":80,"fontsize":14,"fontfamily":"Microsoft Yahei","textalign":"left",}}]},{"id":2,"bgcolor":"rgb(0,0,0)","url":"./images/2.jpg","elements":[ ??//存放元素{"type":"img","url":"./images/user.jpg","style":{"width":80,"height":80,"left":20,"top":20,"border":0,"borderRadius":100 //100表示画原形图片 0表示矩形图片 0-100表示圆角图片}},{"type":"txt","content":"何小姐的博客","style":{"color":"red","left":115,"top":55,"fontsize":20,"fontfamily":"Microsoft Yahei","textalign":"left",}},{"type":"txt","content":"http://www.cnblogs.com/heyujun-/","style":{"color":"red","left":115,"top":80,"fontsize":14,"fontfamily":"Microsoft Yahei","textalign":"left",}}]},{"id":3,"bgcolor":"rgb(0,0,0)","url":"./images/3.jpg","elements":[ ??//存放元素{"type":"img","url":"./images/user.jpg","style":{"width":80,"height":80,"left":20,"top":20,"border":0,"borderRadius":100 //100表示画原形图片 0表示矩形图片 0-100表示圆角图片}},{"type":"txt","content":"何小姐的博客","style":{"color":"#fff","left":115,"top":55,"fontsize":20,"fontfamily":"Microsoft Yahei","textalign":"left",}},{"type":"txt","content":"http://www.cnblogs.com/heyujun-/","style":{"color":"#fff","left":115,"top":80,"fontsize":14,"fontfamily":"Microsoft Yahei","textalign":"left",}}]},{"id":4,"bgcolor":"rgb(0,0,0)","url":"./images/4.jpg","elements":[ ??//存放元素{"type":"img","url":"./images/user.jpg","style":{"width":80,"height":80,"left":20,"top":20,"border":0,"borderRadius":100 //100表示画原形图片 0表示矩形图片 0-100表示圆角图片}},{"type":"txt","content":"何小姐的博客","style":{"color":"#fff","left":115,"top":55,"fontsize":20,"fontfamily":"Microsoft Yahei","textalign":"left",}},{"type":"txt","content":"http://www.cnblogs.com/heyujun-/","style":{"color":"#fff","left":115,"top":80,"fontsize":14,"fontfamily":"Microsoft Yahei","textalign":"left",}}]}]}var canvas, ctx;// 根据json的id切换canvas内容function drawPic(id){$.each(json.lists,function(i,v){if(v.id==id){drawBackground(v.url, v);}});}// 绘制背景图的方法function drawBackground(url, v){var tempW=$(‘.temp‘).width(),tempH=$(‘.temp‘).height();canvas=document.getElementById(‘canvas‘);canvas.width=tempW;canvas.height=tempH;ctx=canvas.getContext(‘2d‘);var Img = new Image();// Img.crossOrigin="anonymous"; ?//跨域问题Img.src=url;Img.onload=function(){ctx.save();ctx.drawImage(Img, 0, 0, canvas.width, canvas.height);ctx.restore();$.each(v.elements,function(ii,vv){if(vv.type=="img"){drawImg(vv.url, vv.style);}else if(vv.type=="txt"){drawTxt(vv.content, vv.style);}});}}// 绘制圆形/圆角/矩形图片元素的方法function drawImg(url, style){var l=style.left,t=style.top,w=style.width,h=style.height;var Img=new Image();// Img.crossOrigin="anonymous"; ?//跨域问题Img.src=url;Img.onload=function(){ctx.save();if(style.borderRadius == 0){ctx.drawImage(Img, l, t, w, h);}else if(style.borderRadius > 0 && style.borderRadius < 100){}else if(style.borderRadius==100){var d = w; ???var cx = l + w/2; ???var cy = t + w/2; ???ctx.arc(cx, cy, w/2, 0, 2 * Math.PI); ???ctx.clip(); ???ctx.drawImage(Img, l, t, d, d);}ctx.restore();}}// 绘制文字的方法function drawTxt(cont, style){ctx.beginPath();ctx.fillStyle = style.color;ctx.font = style.fontsize+‘px ‘+style.fontfamily;ctx.textAlign = style.textalign;ctx.fillText(cont, style.left, style.top);ctx.fill();ctx.closePath();}drawPic(1);
这样就实现了效果,由于跨域问题,这里的生成图片就略过了。
当然这种方法会有一个生成图片的时间段,导致页面看起来是在加载中,看个人怎么取舍。
参考:移动端页面使用rem来做适配 https://www.jianshu.com/p/eb05c775d3c6
如图有侵权,请联删。
解析json结构绘制canvas
原文地址:https://www.cnblogs.com/heyujun-/p/8908000.html