天天看點

canvas,讓脆片飛一會兒

canvas,讓脆片飛一會兒

http://www.hui12.com/nbin/csdn/canvasBg/demo.html

https://nbin2008.github.io/demo/canvasBg/index.html

代碼:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="CanvasBg.js"></script>
	</head>
	<body>
		<canvas id="mycanvas" width="400" height="400" style="border: 1px solid #000;"></canvas>
		<canvas id="mycanvas2" width="400" height="400" style="border: 1px solid #000;"></canvas>
		
		<script type="text/javascript">
			var mycanvas = document.getElementById("mycanvas");
			var mycanvas2 = document.getElementById("mycanvas2");
			var bg = "bg.png"

			
			var c = new CanvasBg({
				mycanvas: mycanvas,
				bg: bg,
				bgNum: 8
			});
			var c2 = new CanvasBg({
				mycanvas: mycanvas2
			})
		</script>
	</body>
</html>
           
<pre name="code" class="javascript">(function(window){
	function CanvasBg(e){
		this.init(e);
	};
	var proto = {
		init: function(e){
			this.before(e);
			this.ddraw();
		},
		before: function(e){
			var This = this;
			this.mycanvas = e.mycanvas;
			this.width = this.mycanvas.width;
			this.height = this.mycanvas.height;
			this.bgNum = e.bgNum || 0;
			this.cache = [];
			var mycanvas = this.mycanvas;
			var myc = mycanvas.getContext('2d');
			var bg = e.bg;
			if( bg ){
				var img = new Image();
				img.src = bg;
				this.bg = img;
				img.onload = function(){
					This.create();
				};
			}else{
				this.bg = false;
				this.create();
			};
		},
		create: function(){
			var This = this,	
				width = this.width,
				height = this.height,
				distance = Math.sqrt((width/2)*(width/2)+(height/2)*(height/2)),
				cache = this.cache;
			this.distance = Math.round(distance);
				
			setInterval(function(){
					var length = This.cache.length;
					if( length < 300 ){
						fnCreate();
					};
			},100);
			function fnCreate(){
				var angle = getAngle(),
					speed = getSpeed(),
					sScale = scale12(),
					bgIndex = getBg(This.bgNum);
				cache.push({
					angle: angle,
					distanceNow: Math.round(distance),
					speed: speed,
					sScale: sScale,
					bgIndex: bgIndex
				});
			};
			function getBg(n){
				return Math.round(Math.random()*(n-1));
			};
			function getSpeed(){
				return Math.round(Math.random()*8+1)/1;
			};
			function scale12(){
				return (Math.random()+1);
//				return 1;
			}
			function getAngle(){
				var n = Math.round(Math.random()*360);
				/*var a = Math.atan(height/width)*180/Math.PI;
				while( (n>=a && n<=180-a) || (n>=a+180 && n<360-a) ){
					n = Math.round(Math.random()*360);
					max = Math.atan(height/width);
				};*/
				return n;
			};
		},
		ddraw: function(){
			var This = this,
				bg = this.bg,
				width = this.width,
				height = this.height,
				mycanvas = this.mycanvas,
				myc = mycanvas.getContext('2d'),
				cache = this.cache;
			
			setInterval(draw, 100);
			function draw(){
				myc.clearRect(0,0,width,height);
				myc.globalCompositeOperation = 'lighter';
				var i = cache.length-1;
				var distance = This.distance;
				while(i>= 0){
					var mycbg = createBg(i);
					var distanceNow = cache[i]["distanceNow"];
					var angle = cache[i]["angle"];
					myc.save();
					myc.translate(width/2, height/2);
					myc.rotate(angle*Math.PI/180);
					myc.drawImage(mycbg,distanceNow,0);
					myc.restore();
					i--;
				};
			};
			function createBg(i){
				var bgCanvas = document.createElement('canvas');
					bgCanvas.width = 100;
					bgCanvas.height = 100;
					smyc = bgCanvas.getContext('2d'),
					distance = This.distance,
					mScale = cache[i]["distanceNow"]/distance
				smyc.scale(cache[i]['sScale'],cache[i]['sScale']);
				smyc.scale(mScale,mScale);
				mScale *= 1.2;
				mScale = mScale<=0.2?0.2:mScale;
				smyc.globalAlpha = mScale;
				if( bg ){
					smyc.drawImage(bg, 50*cache[i]['bgIndex'], 0, 50, 50, 0, 0, 50, 50 );
				}else{
					if( cache[i]['crisp'] ){
						cache[i]['crisp'](smyc);
					}else{
						cache[i]['crisp'] = createCrisp(smyc);
					};	
				};
				return bgCanvas;
			};
			function createCrisp(smyc){
				var tmpArr = [],
					i = 0,
					n = gShape();
				smyc.beginPath()
				while( i<=n ){
					tmpArr.push([gCoord(), gCoord()])
					i++;
				};
				tmpArr.push([gColor(),gColor(),gColor()]);
				function gShape(){
					return Math.round(Math.random()*1+3);
				};
				function gCoord(){
					return Math.round(Math.random()*50);
				};
				function gColor(){
					return Math.round(Math.random()*255);
				};
				
				var tmpFn = function(smyc){
					for( var z=0,l=tmpArr.length; z<l; z++ ){
						var tmp = tmpArr[z];
						if( tmp.length == 2 ){
							if(z==0){
								smyc.beginPath();
								smyc.moveTo(tmp[0], tmp[1]);
							}else{
								smyc.lineTo(tmp[0], tmp[1]);
							};
							if( z==l-2 ){
								smyc.closePath();
							}
						}else{
							smyc.fillStyle = "rgb("+ tmp[0] +","+ tmp[1] +","+ tmp[2] +")";
							smyc.fill();
						}
					};
				};
				tmpFn(smyc);
				return tmpFn;
			};
			
			setInterval(change,100);
			function change(){
				var i=cache.length-1;
				while( i>=0 ){
					cache[i]["distanceNow"] -= cache[i]['speed'];
					if( cache[i]['distanceNow']<=0 ){
						cache.splice(i,1);
					};
					i--;
				};
			};
		}
	};
	CanvasBg.prototype = proto;
	window.CanvasBg = CanvasBg;
})(window);
           

使用方法:

var c = new CanvasBg({mycanvas: mycanvas,bg: bg,bgNum: 8});

var c2 = new CanvasBg({mycanvas: mycanvas2})

new CanvasBg對象,接受一個json資料。

mycanvas:canvas元素

bg:使用自己的圖檔,可選參數

bgNum:自己圖檔上脆片的個數,和bg同時使用。

如果使用自己的圖檔,則圖檔有規範:以50*50像素,從左往右

canvas,讓脆片飛一會兒

效果邏輯部分:

before: function(e){
	var This = this;
	this.mycanvas = e.mycanvas;
	this.width = this.mycanvas.width;
	this.height = this.mycanvas.height;
	this.bgNum = e.bgNum || 0;
	this.cache = [];
	var mycanvas = this.mycanvas;
	var myc = mycanvas.getContext('2d');
	var bg = e.bg;
	if( bg ){
		var img = new Image();
		img.src = bg;
		this.bg = img;
		img.onload = function(){
			This.create();
		};
	}else{
		this.bg = false;
		this.create();
	};
}
           

這個方法是判斷有沒有圖檔參數,最後都是運作create()方法。cache為數組,放脆片資料用

create: function(){
	var This = this,	
		width = this.width,
		height = this.height,
		distance = Math.sqrt((width/2)*(width/2)+(height/2)*(height/2)),
		cache = this.cache;
	this.distance = Math.round(distance);
		
	setInterval(function(){
<pre name="code" class="javascript"><span style="white-space:pre">		</span>var length = This.cache.length;
		if( length < 300 ){
			fnCreate();
		};
           

},100);function fnCreate(){var angle = getAngle(),<span style="white-space:pre"> </span>//脆片出現的角度speed = getSpeed(),<span style="white-space:pre"> </span>//脆皮運作的速度sScale = scale12(),<span style="white-space:pre"> </span>//圖檔開始位置時的大小,使用1-2之間的随機數縮放bgIndex = getBg(This.bgNum);<span style="white-space:pre"> </span>//圖檔上面有多少個脆片,取随機位置cache.push({angle: angle,distanceNow: Math.round(distance),<span style="white-space:pre"> </span>//這個是脆片對應的位置,一直會變化,初始值與distance相等。speed: speed,sScale: sScale,bgIndex: bgIndex});};function getBg(n){return Math.round(Math.random()*(n-1));};function getSpeed(){return Math.round(Math.random()*8+1)/1;};function scale12(){return (Math.random()+1);}function getAngle(){var n = Math.round(Math.random()*360);return n;};}

這個方法為cache資料構造。diatance:以canvas的中心為中點(width/2,height/2),中點到canvas原點(0,0)的距離,因為圖檔都是從外往裡彙聚的。這個數值不做更改,為固定值。

getAngle():脆片出現的軌迹,預設是全屏,傳回的是0-360的數字。修改這裡的傳回值,可以設定脆片出現的範圍。以canvas的中心為中點,順時針方向為對應角度的出現範圍。

ddraw: function(){
	var This = this,
		bg = this.bg,
		width = this.width,
		height = this.height,
		mycanvas = this.mycanvas,
		myc = mycanvas.getContext('2d'),
		cache = this.cache;
	
	setInterval(draw, 100);
	function draw(){
		myc.clearRect(0,0,width,height);
		myc.globalCompositeOperation = 'lighter';
		var i = cache.length-1;
		var distance = This.distance;
		while(i>= 0){
			var mycbg = createBg(i);
			var distanceNow = cache[i]["distanceNow"];<span style="white-space:pre">	</span>//與diatance的值做比列,這個很重要
			var angle = cache[i]["angle"];<span style="white-space:pre">		</span>//脆片的接口
			myc.save();
			myc.translate(width/2, height/2);<span style="white-space:pre">	</span>//位移到canvas中點,距離
			myc.rotate(angle*Math.PI/180);<span style="white-space:pre">		</span>//位移到canvas中點,角度
			myc.drawImage(mycbg,distanceNow,0);<span style="white-space:pre">	</span>//渲染
			myc.restore();
			i--;
		};
	};
	function createBg(i){
		var bgCanvas = document.createElement('canvas');
			bgCanvas.width = 100;
			bgCanvas.height = 100;
			smyc = bgCanvas.getContext('2d'),
			distance = This.distance,
			mScale = cache[i]["distanceNow"]/distance
		smyc.scale(cache[i]['sScale'],cache[i]['sScale']);<span style="white-space:pre">	</span>//預設建構脆片的大小,1-2之間
		smyc.scale(mScale,mScale);<span style="white-space:pre">	</span>//脆片運動就是根據這個比列,很重要
		mScale *= 1.2;<span style="white-space:pre">		</span>//乘以1.2,脆片在往中點彙聚的過程中,有時候還比較遠就消失了,是以做了這個方法
		mScale = mScale<=0.2?0.2:mScale;
		smyc.globalAlpha = mScale;
		if( bg ){<span style="white-space:pre">	</span>//以雪碧圖為脆片
			smyc.drawImage(bg, 50*cache[i]['bgIndex'], 0, 50, 50, 0, 0, 50, 50 );
		}else{<span style="white-space:pre">		</span>//随機脆片
			if( cache[i]['crisp'] ){
				cache[i]['crisp'](smyc);
			}else{
				cache[i]['crisp'] = createCrisp(smyc);
			};	
		};
		return bgCanvas;
	};
	function createCrisp(smyc){
		var tmpArr = [],
			i = 0,
			n = gShape();
		smyc.beginPath()
		while( i<=n ){
			tmpArr.push([gCoord(), gCoord()])
			i++;
		};
		tmpArr.push([gColor(),gColor(),gColor()]);
		function gShape(){
			return Math.round(Math.random()*1+3);
		};
		function gCoord(){
			return Math.round(Math.random()*50);
		};
		function gColor(){
			return Math.round(Math.random()*255);
		};
		
		var tmpFn = function(smyc){
			for( var z=0,l=tmpArr.length; z<l; z++ ){
				var tmp = tmpArr[z];
				if( tmp.length == 2 ){
					if(z==0){
						smyc.beginPath();
						smyc.moveTo(tmp[0], tmp[1]);
					}else{
						smyc.lineTo(tmp[0], tmp[1]);
					};
					if( z==l-2 ){
						smyc.closePath();
					}
				}else{
					smyc.fillStyle = "rgb("+ tmp[0] +","+ tmp[1] +","+ tmp[2] +")";
					smyc.fill();
				}
			};
		};
		tmpFn(smyc);
		return tmpFn;
	};
	
	setInterval(change,100);
	function change(){
		var i=cache.length-1;
		while( i>=0 ){
			cache[i]["distanceNow"] -= cache[i]['speed'];
			if( cache[i]['distanceNow']<=0 ){
				cache.splice(i,1);
			};
			i--;
		};
	};
}
           

繪制canvas效果的主要部分。

draw()方法:實時渲染,一直根據cache中的資料做渲染

createBg():建立bgcanvas給draw方法使用

createCrisp():如果沒有傳入圖檔,則為createBg實時建立bg

主要使用的canvasAPI:

translate() 脆片的位置/距離

rotate() 脆片的位置/角度

scale() 脆片的大小和透明度

drawImage() 背景建構

function change(){
	var i=cache.length-1;
	while( i>=0 ){
		cache[i]["distanceNow"] -= cache[i]['speed'];
		if( cache[i]['distanceNow']<=0 ){
			cache.splice(i,1);
		};
		i--;
	};
};
           

因為脆片是不停的在運動的,是以肯定對應的資料在變化,這個方法是更改distanceNow的值,同時設定臨界點,滿足臨界點則從cache中删除這個資料。

=================追加修改======================

優化1:

setInterval(function(){
				fnCreate();
			},50);
			function fnCreate(){
				var angle = getAngle(),
					speed = getSpeed(),
					sScale = scale12(),
					bgIndex = getBg(This.bgNum);
				
				for( var i=0, len=cache.length; i<len; i++){
					if( cache[i]["isEnd"] ){
						cache[i] = {
								angle: angle,
								distanceNow: Math.round(distance),
								speed: speed,
								sScale: sScale,
								bgIndex: bgIndex,
								isEnd: false,
						};
						return;
					};
				};
				cache.push({
					angle: angle,
					distanceNow: Math.round(distance),
					speed: speed,
					sScale: sScale,
					bgIndex: bgIndex,
					isEnd: false,
				});
			};
           
function change(){
				var i=cache.length-1;
				while( i>=0 ){
					cache[i]["distanceNow"] -= cache[i]['speed'];
					if( cache[i]['distanceNow']<=0 ){
						cache[i]["isEnd"] = true;
					};
					i--;
				};
			};
           

優化2:

function createBg(i){
				var bgCanvas;
				if( bgCanvasJson[i] ){
					bgCanvas = bgCanvasJson[i]
				}else{
					var c = document.createElement('canvas');
					c.width = 100;
					c.height = 100;
					bgCanvasJson[i] = c;
					bgCanvas = bgCanvasJson[i];
				};
				var smyc = bgCanvas.getContext('2d');
				smyc.save();
				smyc.clearRect(0,0,100,100);
				distance = This.distance,
				mScale = cache[i]["distanceNow"]/distance
				smyc.scale(cache[i]['sScale'],cache[i]['sScale']);
				smyc.scale(mScale,mScale);
				mScale *= 1.2;
				mScale = mScale<=0.2?0.2:mScale;
				smyc.globalAlpha = mScale;
				if( bg ){
					smyc.drawImage(bg, 50*cache[i]['bgIndex'], 0, 50, 50, 0, 0, 50, 50 );
				}else{
					if( cache[i]['crisp'] ){
						cache[i]['crisp'](smyc);
					}else{
						cache[i]['crisp'] = createCrisp(smyc);
					};	
				};
				smyc.restore();
				return bgCanvas;
			};