1. 程式人生 > >解析json結構繪制canvas

解析json結構繪制canvas

屏幕尺寸 eve brush list bound scale type document borde

在工作中偶爾會遇到繪制轉發卡/邀請卡的業務,且這個轉發卡/邀請卡的風格會有很多,要求最後生成圖片。這時候如果使用一張圖片繪制一個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