Canvas是HTML5中非常重要而且有用的东西,我们可以在Canvas上绘制任意的元素,就像你制作Flash一样。今天我们就在Canvas上来制作一款火焰发射的效果。就像古代的火球炮一样,而且可以在浏览器边缘反弹,感觉会比较屌。来看看效果图:
我们可以在这里查看火焰球的DEMO演示
当然,我们要来分析一下源代码,主要是一些JS代码。
首先很简单地在页面上放一个canvas标签,并且给它点简单的样式:
<canvas></canvas>
canvas{ position: absolute; height: 100%; width: 100%; left: 0; top: 0; cursor: crosshair; }
接下来就来分析一下JS代码。我们来逐步分解JS。
由于这个是二维动画,所以我们利用canvas的getContext方法来返回一个对象,这个对象包含我们对二维动画操作的API,代码如下:
canvas = document.querySelector('canvas'); ctx = canvas.getContext('2d');
下面我们来定义粒子:
particles = {}; newParticle = (function(){ var nextIndex = 0; return function(x,y,r,o,c,xv,yv,rv,ov){ particles[++nextIndex] = { index: nextIndex, x: x, y: y, r: r, o: o, c: c, xv: xv, yv: yv, rv: rv, ov: ov }; }; })();
然后我们来定义火球:
fireballs = {}; newFireball = (function(){ var nextIndex = 0; return function(x,y,xv,yv,life){ fireballs[++nextIndex] = { index: nextIndex, x: x, y: y, xv: xv, yv: yv, life: life }; }; })();
这里life表示火球的生命周期,下面我们可以看到,life值会随着火球发射力度的改变而改变。
接下来是定义鼠标拖动弹弓,准备发射火球:
mouse = {x:0,y:0,d:0}; onmousemove = function(e){ mouse.x = e.clientX-o.x; mouse.y = e.clientY-o.y; var dx = mouse.x - pos1.x, dy = mouse.y - pos1.y; mouse.d = Math.sqrt(dx*dx+dy*dy); }; charging = false; pos1 = {x:0,y:0}; showInstructions = true; onmousedown = function(e){ pos1.x = mouse.x; pos1.y = mouse.y; charging = true; showInstructions = false; }; onmouseup = function(){ if(charging){ newFireball( mouse.x, mouse.y, (pos1.x-mouse.x)*0.03, (pos1.y-mouse.y)*0.03, 600 ); charging = false; } };
可以看到,当鼠标按键弹起时,新建一个火球,并初始化life值。
下面是火球运动时的动画执行代码,包括碰到浏览器边缘时的反射效果:
time = 0; requestAnimationFrame(loop = function(){ ctx.setTransform(1,0,0,1,0,0); ctx.globalCompositeOperation = 'source-over'; ctx.globalAlpha = 1; ctx.fillStyle = bgColor; ctx.fillRect(0,0,width,height); ctx.translate(o.x,o.y); if(charging){ var c = Math.floor(30+mouse.d/2); ctx.strokeStyle = 'rgba('+c+','+c+','+c+',1)'; ctx.lineWidth = 4; ctx.beginPath(); ctx.moveTo(pos1.x,pos1.y); ctx.lineTo(mouse.x,mouse.y); ctx.lineCap = 'round'; ctx.stroke(); } if(showInstructions){ pos1.x = -70; pos1.y = -35; if(time<10){ var x = -70, y = -35, r = 30-time*2, a = time/10; }else if(time<80){ var x = (time-10)*2-70, y = (time-10)-35, r = 10, a = 1; }else if(time<90){ var x = 70, y = 35, r = 10+(time-80)*2, a = 1-(time-80)/10; }else if(time<140){ var x = 70, y = 35, r = 30, a = 0; } var dx = pos1.x-x, dy = pos1.y-y, d = Math.sqrt(dx*dx+dy*dy); if(time<80&&time>10){ ctx.globalCompositeOperation = 'source-over'; ctx.globalAlpha = 1; var c = Math.floor(30+d/2); ctx.strokeStyle = 'rgba('+c+','+c+','+c+',1)'; ctx.lineWidth = 4; ctx.beginPath(); ctx.moveTo(pos1.x,pos1.y); ctx.lineTo(x,y); ctx.lineCap = 'round'; ctx.stroke(); } if(time<140){ ctx.globalCompositeOperation = 'source-over'; ctx.globalAlpha = a; ctx.beginPath(); ctx.arc(x,y,r,0,Math.PI*2); ctx.lineWidth = 2; ctx.strokeStyle = '#aaa'; ctx.stroke(); } if(time==80){ newFireball( x, y, dx*0.03, dy*0.03, 240 ); } time = (time+1)%180; } ctx.globalCompositeOperation = 'lighter'; for(var i in particles){ var p = particles[i]; ctx.beginPath(); ctx.arc(p.x,p.y,p.r,0,Math.PI*2); ctx.globalAlpha = p.o; ctx.fillStyle = p.c; ctx.fill(); } for(var i in particles){ var p = particles[i]; p.x += p.xv; p.y += p.yv; p.r += p.rv; p.o += p.ov; if(p.r<0)delete particles[p.index]; if(p.o<0)delete particles[p.index]; } for(var i in fireballs){ f = fireballs[i]; var numParticles = Math.sqrt(f.xv*f.xv+f.yv*f.yv)/5; if(numParticles<1)numParticles=1; var numParticlesInt = Math.ceil(numParticles), numParticlesDif = numParticles/numParticlesInt; for(var j=0;j<numParticlesInt;j++){ newParticle( f.x-f.xv*j/numParticlesInt, f.y-f.yv*j/numParticlesInt, 7, numParticlesDif, particleColor, Math.random()*0.6-0.3, Math.random()*0.6-0.3, -0.3, -0.05*numParticlesDif ); } f.x += f.xv; f.y += f.yv; f.yv += gravity; var boundary; if(f.y<(boundary = edge.top+7)){ f.y = boundary; f.yv *= -1; }else if(f.y>(boundary = edge.bottom-7)){ f.y = boundary; f.yv *= -1; } if(f.x>(boundary = edge.right-7)){ f.x = boundary; f.xv *= -1; }else if(f.x<(boundary = edge.left+7)){ f.x = boundary; f.xv *= -1; } if(--f.life<0)delete fireballs[f.index]; } requestAnimationFrame(loop); });
Atas ialah kandungan terperinci HTML5 Canvas实现火焰效果像火球发射一样的示例代码. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!