您的位置:首页 > Web前端

canvas,让脆片飞一会儿

2015-10-18 18:20 288 查看

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像素,从左往右



效果逻辑部分:

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);/*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;};}

这个方法为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;
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息