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); });
以上是HTML5 Canvas實現火焰效果像火球發射一樣的範例程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!