1.一個粒子的運動
一個半徑為3的實心圓以畫布的中心(canvas.width/2,canvas.height/2)為起點,沿著一條曲線進行移動,撰寫如下的HTML代碼,
<!DOCTYPE html> <html> <head> <title>粒子的運動</title> </head> <body> <script> var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); document.body.appendChild(canvas); canvas.width = window.innerWidth; canvas.height = window.innerHeight; ctx.beginPath(); ctx.fillStyle = 'rgba(0, 0, 0, 1)'; ctx.fillRect(0, 0, canvas.width, canvas.height); var angle = 90; var pos = [canvas.width/2,canvas.height/2]; var speed = 6; var curve = 2.5; var index = 1; var color = 'rgba(69,204,255,.95)'; function draw () { var radians = angle*Math.PI/180; pos[0] += Math.cos(radians)* speed+Math.cos(index); pos[1] += Math.sin(radians)* speed+Math.sin(index); angle += curve; ctx.fillStyle = color; ctx.beginPath(); ctx.arc(pos[0],pos[1],3,0,2*Math.PI); ctx.fill(); fade(); window.requestAnimationFrame(draw); } function fade () { ctx.beginPath(); ctx.fillStyle = 'rgba(0, 0, 0, .03)'; ctx.fillRect(0, 0, canvas.width, canvas.height); } window.requestAnimationFrame(draw); </script> </body> </html>View Code
在瀏覽器中打開包含這段HTML代碼的html檔案,可以在瀏覽器視窗中呈現出如圖1所示的影片效果,

圖1 一個實心圓的運動
2.爆裂的粒子
將圖1中的半徑為3的實心圓作為一個基本粒子,抽象一個粒子物件Particle,該物件有表示粒子運動的起始位置的angle、粒子運動的當前位置pos(初始值為畫布中心[canvas.width/2,canvas.height/2])、粒子運動速度speed、粒子運動角度變化量curve、粒子顏色color和例子編號index等屬性;為該粒子物件定義move和draw兩個方法,分別完成粒子的位置變化和粒子繪制操作,
為設定方便起見,給在畫布中心爆裂的粒子預設定3個引數,用變數config來表示,config.num、config.speed和config.curve分別表示3個引數分量,其中,config.num表示畫布中爆裂出的粒子個數,由它計算出粒子運動的起始位置angle;config.speed和config.curve則分別對應粒子運動速度speed和粒子運動角度變化量curve,
撰寫的HTML檔案如下,
<!DOCTYPE html> <html> <head> <title>爆裂的粒子</title> </head> <body> <script> var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; document.body.appendChild(canvas); var particles = []; var colors = [ 'rgba(69,204,255,.95)', 'rgba(73,232,62,.95)', 'rgba(255,212,50,.95)', 'rgba(232,75,48,.95)', 'rgba(178,67,255,.95)' ]; var config = {}; config.num=150; config.speed=1; config.curve=0.5; ctx.beginPath(); ctx.fillStyle = 'rgba(0, 0, 0, 1)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fill(); particles.length = 0; createParticles(); window.requestAnimationFrame(draw); function createParticles() { var n = config.num; for (var i=0; i<n; i++) { var angle = (360/n)*(i+1); particles.push(new Particle(angle,i)); } } function draw () { for (var i=0; i<particles.length; i++) { var p = particles[i]; p.move(); p.draw(); } fade(); window.requestAnimationFrame(draw); } function Particle (angle,index) { this.angle = angle; this.speed = config.speed; this.curve = config.curve; this.color = colors[index%5]; this.index = index; this.pos = [canvas.width/2, canvas.height/2]; } Particle.prototype.move = function() { this.angle += this.curve; var radians = this.angle*Math.PI/180; this.pos[0] += Math.cos(radians)*this.speed+Math.cos(this.index); this.pos[1] += Math.sin(radians)*this.speed+Math.sin(this.index); } Particle.prototype.draw = function () { ctx.fillStyle = this.color; ctx.beginPath(); ctx.arc(this.pos[0],this.pos[1],3,0,2*Math.PI); ctx.fill(); } function fade () { ctx.beginPath(); ctx.fillStyle = 'rgba(0, 0, 0, .03)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fill(); } </script> </body> </html>View Code
在瀏覽器中打開包含這段HTML代碼的html檔案,可以在瀏覽器視窗中呈現出如圖2所示的影片效果,150個粒子包在畫布中心爆裂開后,四散運動起來,
圖2 爆裂的粒子(num=150,speed = 1,curve = 0.5)
為3個引數設定不同的值,可以呈現出不同的影片效果,給出4組不同值的設定,呈現的影片效果分別如圖3、圖4、圖5和圖6所示,為避免圖形檔案過大,下列的影片程序均只錄制一個片段,完整的影片演示程序請讀者自己打開HTML檔案運行程式觀看,
圖3 爆裂的粒子(num=300,speed = 6,curve =1.5)

圖4 爆裂的粒子(num=300,speed = 2,curve = 1)

圖5 爆裂的粒子(num=300,speed = 100,curve =180)
圖6 爆裂的粒子(num=100,speed = 120,curve =10)
3.可設定引數的爆裂的粒子影片特效
由圖2~圖6可知,不同的引數設定,爆裂開來的粒子運動所呈現的影片效果不同,為此,我們提供文本框輸入預設數值的方式對3個引數的值進行設定,設定完成后,單擊“Burst!”按鈕,按設定的引數進行影片效果的呈現,
撰寫的HTML代碼如下,
<!DOCTYPE html> <html> <head> <title>爆裂的粒子(可設定引數)</title> <style> form { position:absolute; top:0; left:0; z-index:100; background-color:rgba(200,200,200,.8); padding:8px; font-size:90%; } form input[type=text] { width:30px; border:1px solid #000; text-align:center; } form button { margin:4px auto; border:1px solid #000; display:block; } </style> </head> <body> <form id="settings" onsubmit="return false"> Particles<br/> <input type="text" id="inNum" value="150"/><br/> Speed<br/> <input type="text" id="inSpeed" value="2"/><br/> Curve<br/> <input type="text" id="inCurve" value="1"/><br/> <button id="btnClear">Clear</button> <button id="btnSet">Burst!</button><br/> </form> <script> var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; document.body.appendChild(canvas); var particles = []; var config = {}; var settings = document.getElementById('settings'); start(); window.requestAnimationFrame(draw); function createParticles() { var n = config.num; for (var i=0; i<n; i++) { var angle = (360/n)*(i+1); particles.push(new Particle(angle,i)); } } function draw () { for (var i=0; i<particles.length; i++) { var p = particles[i]; p.move(); p.draw(); } fade(); window.requestAnimationFrame(draw); } function Particle (angle,index) { this.angle = angle; this.speed = config.speed; this.curve = config.curve; this.color = randColor(90,255) this.index = index; this.pos = [canvas.width/2, canvas.height/2]; } Particle.prototype.move = function() { this.angle += this.curve; var radians = this.angle*Math.PI/180; this.pos[0] += Math.cos(radians)*this.speed+Math.cos(this.index); this.pos[1] += Math.sin(radians)*this.speed+Math.sin(this.index); } Particle.prototype.draw = function () { ctx.fillStyle = this.color; ctx.beginPath(); ctx.arc(this.pos[0],this.pos[1],3,0,2*Math.PI); ctx.fill(); } function randColor(min, max) { var r = Math.floor(Math.random()*(max-min)+min); var g = Math.floor(Math.random()*(max-min)+min); var b = Math.floor(Math.random()*(max-min)+min); return 'rgba('+r+','+g+','+b+',0.95)'; } function fade () { ctx.beginPath(); ctx.fillStyle = 'rgba(0, 0, 0, .03)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fill(); } function clear () { ctx.beginPath(); ctx.fillStyle = 'rgba(0, 0, 0, 1)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fill(); particles.length = 0; } function start() { config.num = parseFloat(settings.inNum.value); config.speed = parseFloat(settings.inSpeed.value); config.curve = parseFloat(settings.inCurve.value); createParticles(); } settings.btnSet.addEventListener("click", start); settings.btnClear.addEventListener("click", clear); </script> </body> </html>View Code
在瀏覽器中打開包含這段HTML代碼的html檔案,可以在瀏覽器視窗中呈現出如圖7所示的影片效果,
圖7 爆裂的粒子(單擊一次Burst!按鈕)
在頁面中,單擊“Clear”按鈕,會清屏,同時置粒子陣列的長度為0,相當于頁面中不再有運動的粒子,
單擊“Burst!”按鈕,會讀取設定的引數值,同時呼叫createParticles();向粒子陣列中添加從畫布中心爆裂開的粒子,注意:是添加,若陣列中原來有運動的粒子,則原來運動的粒子會繼續運動,這樣,多次單擊“Burst!”按鈕,會呈現出更多有變化的影片效果,
例如,連續單擊三次“Burst!”按鈕,在瀏覽器視窗呈現出如圖8所示的影片效果,
圖8 爆裂的粒子(單擊三次Burst!按鈕)
4.粒子包在畫布中心自動爆裂
從圖2和圖7的影片程序可以看出,一個粒子包在畫布中心爆裂開來后,粒子四散運動,逐漸超出畫布范圍,最侄訓布一片空白,雖然我們可以像圖8的效果那樣,通過不斷單擊“Burst!”按鈕在畫布中心爆裂開新的粒子包,但這需要人為控制,當然,也可以不斷呼叫createParticles()函式,在畫布中心爆裂新的粒子包,但函式呼叫的時機需要仔細考慮,
一個可行的辦法是:每當一個粒子運動超出了畫布范圍,可以認為該粒子消亡了,從particles陣列中洗掉該粒子物件,當粒子陣列particles中剩余的粒子數不足config.num的一半時,自動呼叫createParticles()函式在畫布中心爆裂一個新的粒子包,向粒子陣列中添加爆裂的粒子,
撰寫的HTML檔案如下,
<!DOCTYPE html> <html> <head> <title>爆裂的粒子</title> </head> <body> <script> var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; document.body.appendChild(canvas); var particles = []; var colors = [ 'rgba(69,204,255,.95)', 'rgba(73,232,62,.95)', 'rgba(255,212,50,.95)', 'rgba(232,75,48,.95)', 'rgba(178,67,255,.95)' ]; var config = {}; config.num=150; config.speed=1; config.curve=0.5; ctx.beginPath(); ctx.fillStyle = 'rgba(0, 0, 0, 1)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fill(); particles.length = 0; createParticles(); window.requestAnimationFrame(draw); function createParticles() { var n = config.num; for (var i=0; i<n; i++) { var angle = (360/n)*(i+1); particles.push(new Particle(angle,i)); } } function draw () { for (var i=particles.length-1;i>=0; i--) { var p = particles[i]; p.move(); p.draw(); if (p.pos[0]<0 || p.pos[0]>canvas.width || p.pos[1]<0 || p.pos[1]>canvas.height) particles.splice(i, 1); } fade(); if (particles.length<=config.num/2) createParticles(); window.requestAnimationFrame(draw); } function Particle (angle,index) { this.angle = angle; this.speed = config.speed; this.curve = config.curve; this.color = colors[index%5]; this.index = index; this.pos = [canvas.width/2, canvas.height/2]; } Particle.prototype.move = function() { this.angle += this.curve; var radians = this.angle*Math.PI/180; this.pos[0] += Math.cos(radians)*this.speed+Math.cos(this.index); this.pos[1] += Math.sin(radians)*this.speed+Math.sin(this.index); } Particle.prototype.draw = function () { ctx.fillStyle = this.color; ctx.beginPath(); ctx.arc(this.pos[0],this.pos[1],3,0,2*Math.PI); ctx.fill(); } function fade () { ctx.beginPath(); ctx.fillStyle = 'rgba(0, 0, 0, .03)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fill(); } </script> </body> </html>View Code
在瀏覽器中打開包含這段HTML代碼的html檔案,可以在瀏覽器視窗中呈現出如圖9所示的影片效果,
圖9 不斷爆裂的粒子包
需要說明的是,對于不同的num、speed和curve三個引數的設定,上面的程式大多數情況下運行情況良好,但對于如圖6影片效果所設定的3個引數(num=100,speed = 120,curve =10),呈現的影片效果如圖10所示,

圖10 不斷爆裂的粒子包(num=100,speed = 120,curve =10)
從圖10看出,畫面基本靜止,這主要由于按給定的引數,粒子移動一次就會超出畫布范圍,因而不斷洗掉粒子、添加粒子,每個粒子的移動基本是一次性的,即移動一次就超出畫布范圍消亡了,而圖6之所以可以呈現出影片效果是因為移出畫布的粒子有可能會自己運動回來,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/137460.html
標籤:JavaScript
