解析json结构绘制canvas
Posted heyujun-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解析json结构绘制canvas相关的知识,希望对你有一定的参考价值。
在工作中偶尔会遇到绘制转发卡/邀请卡的业务,且这个转发卡/邀请卡的风格会有很多,要求最后生成图片。这时候如果使用一张图片绘制一个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的主要内容,如果未能解决你的问题,请参考以下文章
Android 应用开发Canvas 精准绘制文字 ( 文本边界坐标解析 | 绘图位置 )