1.一個(gè)沿圓周運(yùn)動(dòng)的圓圈一個(gè)半徑為size的圓圈以畫布的中心(canvas.width/2,canvas.height/2)為起點(diǎn),沿著一個(gè)圓周運(yùn)動(dòng)。編寫如下的HTML代碼。 ![]() <!DOCTYPE html> <html> <head> <title>沿圓周運(yùn)動(dòng)的圓圈</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 =360; var pos = [canvas.width/2,canvas.height/2]; var size = 10; var speed = 1; var curve = 0.5; var color = 'rgba(69,204,255,.95)'; function draw () { var radians = angle*Math.PI/180; pos[0] += Math.cos(radians)* speed; pos[1] += Math.sin(radians)* speed; angle += curve; ctx.strokeStyle = color; ctx.beginPath(); ctx.arc(pos[0],pos[1],size,0,2*Math.PI); ctx.stroke(); window.requestAnimationFrame(draw); } window.requestAnimationFrame(draw); </script> </body> </html> 在瀏覽器中打開包含這段HTML代碼的html文件,可以在瀏覽器窗口中呈現(xiàn)出如圖1所示的動(dòng)畫效果。 圖1 沿圓周運(yùn)動(dòng)的一個(gè)圓圈 由圖1可知,圓圈運(yùn)動(dòng)的起點(diǎn)(canvas.width/2,canvas.height/2)位于運(yùn)動(dòng)所沿的圓周上angle==360°的位置。 2.兩個(gè)沿圓周運(yùn)動(dòng)的圓圈在畫布中放置兩個(gè)圓圈,兩個(gè)圓圈的起點(diǎn)均位于畫布中心(canvas.width/2,canvas.height/2),一個(gè)圓圈從所沿圓周的45°處沿圓周運(yùn)動(dòng),另一個(gè)圓圈從所沿圓周的135°處沿圓周運(yùn)動(dòng)。編寫如下的HTML代碼。 ![]() <!DOCTYPE html> <html> <head> <title>沿圓周運(yùn)動(dòng)的圓圈</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 angle1 =45; var angle2 =135; var pos1 = [canvas.width/2,canvas.height/2]; var pos2 = [canvas.width/2,canvas.height/2]; var size = 10; var speed = 1; var curve = 0.5; var color1 = 'rgba(69,204,255,.95)'; var color2 = 'rgba(255,212,50,.95)'; function draw () { var radians = angle1*Math.PI/180; pos1[0] += Math.cos(radians)* speed; pos1[1] += Math.sin(radians)* speed; angle1 += curve; radians = angle2*Math.PI/180; pos2[0] += Math.cos(radians)* speed; pos2[1] += Math.sin(radians)* speed; angle2 += curve; ctx.strokeStyle = color1; ctx.beginPath(); ctx.arc(pos1[0],pos1[1],size,0,2*Math.PI); ctx.stroke(); ctx.strokeStyle = color2; ctx.beginPath(); ctx.arc(pos2[0],pos2[1],size,0,2*Math.PI); ctx.stroke(); // 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> 在瀏覽器中打開包含這段HTML代碼的html文件,可以在瀏覽器窗口中呈現(xiàn)出如圖2所示的動(dòng)畫效果。
圖2 兩個(gè)沿圓周運(yùn)動(dòng)的圓圈 為了展示圓圈運(yùn)動(dòng)的軌跡,我們?cè)诤瘮?shù)draw()的函數(shù)體中,最后一行語句前加上調(diào)用語句“fade();”,編寫fade()函數(shù)如下: function fade () { ctx.beginPath(); ctx.fillStyle = 'rgba(0, 0, 0, .03)'; ctx.fillRect(0, 0, canvas.width, canvas.height); } 這樣,圓圈運(yùn)動(dòng)軌跡帶長尾效果。在瀏覽器中呈現(xiàn)出如圖3所示的動(dòng)畫效果。
圖3 兩個(gè)沿圓周運(yùn)動(dòng)的圓圈(帶長尾效果) 3.更多沿圓周運(yùn)動(dòng)的圓圈如果要在畫布中讓num個(gè)圓圈沿圓周運(yùn)動(dòng)呢?為此,將圓圈抽象為粒子對(duì)象Particle,該對(duì)象有圓圈在所沿圓周上的起始位置angle、圓圈運(yùn)動(dòng)的當(dāng)前位置pos(初始值為畫布中心[canvas.width/2,canvas.height/2])、圓圈大小size、運(yùn)動(dòng)速度speed、運(yùn)動(dòng)角度變化量curve和圓圈顏色color等屬性;為該對(duì)象定義move和draw兩個(gè)方法,分別完成圓圈的位置變化和圓圈繪制操作。 為設(shè)定方便起見,給沿圓周運(yùn)動(dòng)的圓圈預(yù)設(shè)置4個(gè)參數(shù),用變量config來表示。config.num、config.size 、config.speed和config.curve分別表示4個(gè)參數(shù)分量。其中,config.num表示畫布中參與運(yùn)動(dòng)的圓圈個(gè)數(shù),由它計(jì)算出圓圈在所沿圓周上的起始位置angle。 編寫的HTML文件如下。 ![]() <!DOCTYPE html> <html> <head> <title>沿圓周運(yùn)動(dòng)的圓圈(給定4個(gè)參數(shù))</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); ctx.beginPath(); ctx.fillStyle = 'rgba(0, 0, 0, 1)'; ctx.fillRect(0, 0, canvas.width, canvas.height); 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 = 5; config.size = 2; config.speed = 1; config.curve = 0.5; 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,colors[i%5])); } } 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,color) { this.angle = angle; this.size = config.size; this.speed = config.speed; this.color = color; this.curve = config.curve; 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, this.pos[1] += Math.sin(radians)*this.speed; } Particle.prototype.draw = function () { ctx.strokeStyle = this.color; ctx.beginPath(); ctx.arc(this.pos[0],this.pos[1],this.size,0,2*Math.PI); ctx.stroke(); } function fade () { ctx.beginPath(); ctx.fillStyle = 'rgba(0, 0, 0, .03)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fill(); } </script> </body> </html> 在瀏覽器中打開包含這段HTML代碼的html文件,可以在瀏覽器窗口中呈現(xiàn)出如圖4所示的動(dòng)畫效果。
圖4 沿圓周運(yùn)動(dòng)的圓圈(num=5,size=2,speed = 1,curve = 0.5) 為4個(gè)參數(shù)設(shè)定不同的值,可以呈現(xiàn)出不同的動(dòng)畫效果。給出3組不同值的設(shè)定,呈現(xiàn)的動(dòng)畫效果分別如圖5、圖6和圖7所示。為避免圖形文件過大,下列的動(dòng)畫過程均只錄制一個(gè)片段。完整的動(dòng)畫演示過程請(qǐng)讀者自己打開HTML文件運(yùn)行程序觀看。
圖5 沿圓周運(yùn)動(dòng)的圓圈(num=80,size=4,speed = 1,curve = 0.5)
圖6 沿圓周運(yùn)動(dòng)的圓圈(num=8,size=16,speed = 1.8,curve = 1.8)
圖7 沿圓周運(yùn)動(dòng)的圓圈(num=90,size=100,speed = 2,curve =1) 由圖4~圖7可知,參數(shù)speed 和curve決定了圓圈運(yùn)動(dòng)的軌跡。上面代碼中,各個(gè)圓圈的參數(shù)speed 和curve均相同。能否讓各個(gè)運(yùn)動(dòng)的圓圈的參數(shù)speed 和curve不同,這樣它們的運(yùn)動(dòng)軌跡也不同,呈現(xiàn)出更多的變化呢? 一個(gè)簡(jiǎn)單的辦法是讓參數(shù)speed 和curve在某個(gè)區(qū)間范圍內(nèi)隨機(jī)取值。 例如,修改config參數(shù)的設(shè)置如下: config.num = 80; config.size = 300; config.speed =[1,10]; config.curve = [-0.5,0.5]; 修改function Particle (angle,color)如下: function Particle (angle,color) { this.angle = angle; this.size = config.size; this.speed = rand(config.speed[0],config.speed[1]); this.color = color; this.curve = rand(config.curve[0],config.curve[1]); this.pos = [canvas.width/2, canvas.height/2]; } 增加在區(qū)間[min,max]中取隨機(jī)值的函數(shù)如下: function rand(min, max) { return Math.random()*(max-min)+min; } 其余部分保持不變,則在瀏覽器窗口中呈現(xiàn)出如圖8所示的動(dòng)畫效果。這個(gè)動(dòng)畫效果有點(diǎn)炫酷喲!
圖8 沿圓周運(yùn)動(dòng)的圓圈(num=80,size=300,speed =1~10,curve =-0.5~0.5) 4.可設(shè)置參數(shù)的沿圓周運(yùn)動(dòng)的圓圈由圖4~圖8可知,不同的參數(shù)設(shè)定,沿圓周運(yùn)動(dòng)的圓圈所呈現(xiàn)的動(dòng)畫效果不同。為此,我們提供文本框輸入預(yù)設(shè)數(shù)值的方式對(duì)4個(gè)參數(shù)的值進(jìn)行設(shè)定,設(shè)定完成后,單擊“Go!”按鈕,按設(shè)定的參數(shù)進(jìn)行動(dòng)畫效果的呈現(xiàn)。 編寫的HTML代碼如下。 ![]() <!DOCTYPE html> <html> <head> <title>沿圓周運(yùn)動(dòng)的圓圈(可設(shè)置參數(shù))</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="inBubblesMin" value="150"/> To <input type="text" id="inBubblesMax" value="150"/><br/> Size<br/> <input type="text" id="inSizeMin" value="2"/> To <input type="text" id="inSizeMax" value="2"/><br/> Speed<br/> <input type="text" id="inSpeedMin" value="1"/> To <input type="text" id="inSpeedMax" value="1"/><br/> Curve<br/> <input type="text" id="inCurveMin" value=".5"/> To <input type="text" id="inCurveMax" value=".5"/><br/> <button id="btnClear">Clear</button> <button id="btnSet">Go!</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 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 = {}; var settings = document.getElementById('settings'); start(); window.requestAnimationFrame(draw); function createParticles() { var n = rand(config.num[0],config.num[1]); for (var i=0; i<n; i++) { var angle = (360/n)*(i+1); particles.push(new Particle({ angle:angle, size:rand(config.size[0],config.size[1]), speed:rand(config.speed[0],config.speed[1]), color:colors[i%5], curve:rand(config.curve[0],config.curve[1]) })); } } function draw () { for (var i=0; i<particles.length; i++) { var p = particles[i]; p.move(); p.draw(ctx); } fade(); window.requestAnimationFrame(draw); } function Particle (options) { this.angle = options.angle; this.size = options.size; this.speed = options.speed; this.color = options.color; this.curve = options.curve; 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, this.pos[1] += Math.sin(radians)*this.speed; } Particle.prototype.draw = function (ctx) { ctx.strokeStyle = this.color; ctx.beginPath(); ctx.arc(this.pos[0],this.pos[1],this.size,0,2*Math.PI); ctx.stroke(); } 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.inBubblesMin.value), parseFloat(settings.inBubblesMax.value) ]; config.size = [parseFloat(settings.inSizeMin.value), parseFloat(settings.inSizeMax.value)]; config.speed = [parseFloat(settings.inSpeedMin.value), parseFloat(settings.inSpeedMax.value)]; config.curve = [parseFloat(settings.inCurveMin.value), parseFloat(settings.inCurveMax.value)]; createParticles(); } settings.btnSet.addEventListener("click", start); settings.btnClear.addEventListener("click", clear); function rand(min, max) { return Math.random()*(max-min)+min; } </script> </body> </html> 在瀏覽器中打開包含這段HTML代碼的html文件,可以在瀏覽器窗口中呈現(xiàn)出如圖9所示的動(dòng)畫效果。
圖9 沿圓周運(yùn)動(dòng)的圓圈(單擊一次Go!按鈕) 在頁面中,單擊“Clear”按鈕,會(huì)清屏,同時(shí)置粒子數(shù)組的長度為0,相當(dāng)于頁面中不再有沿圓周運(yùn)動(dòng)的圓圈。 單擊“Go!”按鈕,會(huì)讀取設(shè)置的參數(shù)值,同時(shí)調(diào)用createParticles();向粒子數(shù)組中添加運(yùn)動(dòng)的圓圈。注意:是添加,若數(shù)組中原來有運(yùn)動(dòng)的圓圈,則原來運(yùn)動(dòng)的圓圈會(huì)繼續(xù)運(yùn)動(dòng)。這樣,多次單擊“Go!”按鈕,會(huì)呈現(xiàn)出更多有變化的動(dòng)畫效果。 例如,圖9的動(dòng)畫效果是150個(gè)運(yùn)動(dòng)的圓圈構(gòu)成一個(gè)大圓環(huán)收縮效果。若按一定時(shí)間間隔單擊兩次“Go!”按鈕,應(yīng)該會(huì)呈現(xiàn)出2個(gè)大圓環(huán)交替收縮的動(dòng)畫效果,如圖10所示。
圖10 沿圓周運(yùn)動(dòng)的圓圈(單擊兩次Go!按鈕) 多次單擊“Go!”按鈕添加運(yùn)動(dòng)圓圈的功能設(shè)定很有意思了。這意味著我們可以將上面的動(dòng)畫效果進(jìn)行組合。圖10的動(dòng)畫效果實(shí)質(zhì)是兩個(gè)圖9所示動(dòng)畫效果的組合。 例如,設(shè)定num=150,size=2,speed = 1,curve = 0.5后,單擊“Go!”按鈕,呈現(xiàn)出如圖9所示的動(dòng)畫效果;再設(shè)定num=8,size=16,speed = 1.8,curve = 1.8,單擊“Go!”按鈕(呈現(xiàn)如圖6所示的動(dòng)畫效果)后,圖6和圖9的動(dòng)畫效果組合起來,呈現(xiàn)出如圖11所示的動(dòng)畫效果。 圖11 兩種動(dòng)畫效果的組合 |
|