XML/HTML Code複製內容到剪貼簿
- var P_radius = 8,重力 = 9.8;
-
var 粒子 = this.x
- = 0 = 0;
- this.y = 0 = 0
- ;
this.vx = 0
= -
00
this.vy
= -
0 = 0;
-
this.color = " = " =
" -
this.visible =
-
this.drop-
=
} -
- Particle.prototype
= { -
建構子: 粒子,
paint:function(){ //螢光燈本身為
- ctx.fillStyle
- ctx.fillStyle
ctx.fillStyle-
ctx.fillStyle
- @
ctx.beginPath();
ctx.arc(this.x,this.y,P_radius,0,2*Math.PI);
ctx.fill();
},
- reset:function(x,y,color){ //重設
-
this.x
= x; -
this.y
= y; -
this.vx >
-
this.vy =
this.color
-
this.visible this.visible
- this.visible
this.drop
-
},
isDrop:function(){ //下對上
- this.drop
-
var -
vx = vx = vx = 🎜>
-
this.vx 🎜> =0.5?
},
- update:function(time){ //每個上幀的動作
-
if(this.drop){
-
this.x = this.vx*時間;
-
this.y = this.vy*時間;
-
-
var vy vy
- vy 🎜>
-
if(this.y>
- =canvas.height
以 P_radius
vy
}
-
this.vy- = = =
-
‧ 🎜> canvas.width P_radius||this.y
-P_radius- ||this.y
>- height P_radius){
將中對
}
}
}
}凡
-
粒子物件的屬性比較簡單,就位置,速度,以及是否可視化。方法的話,paint是較差方法,reset是重置(因為粒子要循環利用的,提升性能),isDrop是粒子落下方法,update就是每一幀更新消耗品的動作,更新當消耗品運動超出畫布的稀疏區域時,將其視覺化設定為false,在消耗品容器中儲存起來等待下一次呼叫。
寫好物資對象後,需要考慮讓物資按照位置畫上去如何,同時當物資不需要時能夠讓他做自由落體的動畫了。
先畫背景(原來沒有像素的白點):
-
XML/HTML 程式碼- 將內容複製到剪貼簿
- 函數drawBg(){
-
var tx = (canvas.width-(P_iusd*2*)jjg*
-
for(var i=0=0=0
=-
0=0
=-
0=0=0=8;i ){
- var ty = (canvasheight-((P_hius)yjah);
for(var j
- =j= numData
- [0].length;j ){
- var tt
- tt tt tt
-
if(tt==="/>tt
==="/
-
ty =yjg;
}其他 {
var x (P_radius*2 X_J),
-
; -
- bgctx.FillStyle
;
-
bgctx.beginPath();
-
bgctx.arc(x,y,P_radius,0,2*Math.PI);
-
bgctx.fill();
-
}
-
}
tx =xjg 4*(P_半徑*2 X_J);
}
}
先把背景畫到一個離屏canvas中緩存起來,接下來每一幀重畫的時候就不需要邏輯計算了,直接把那個離屏canvas畫上去就行了。上面的邏輯應該不難理解,就是透過兩個循環,循環8個數字,然後再對每個數字一個點一個點進行繪製,當遇到“/”時,就說明要換行了,把繪製的ty加個換行間隔,再把tx重置,再進行繪製。就這樣,點就可以都畫出來了。效果圖如下:
背景畫好了,就開始根據每一秒的時間,畫數字像素吧。方法主要是這個:
XML/HTML Code複製內容到剪貼簿
- 函數 setTime(時間){
-
var h = 米
= -
米 = 米 🎜>
s-
= s = 時間
- hh
米米
=m
ss
-
var nowdate = h ":" m ":" s;
- var tx
- = (canvas.width-(P_ius)> >顏色 = "";
for(var
- i=0=0=0=
- 0=0=0=0=0
- =nowdate.length;i ){
var n
== nowdate.charAt(i)), -
文字文字
文字-
-
var ty
=
-
- 開關(i){
-
case 0:顏色
case break;
-
案例 3:顏色
-
案例 5:顏色
案例 6:顏色
-
}
for(var - j
=- j
=- text.length;j ){
var tt
if(tt
- ==="/>tt==="/
ty =yjg;
}其他{
-
var x (P_radius*2 X_J),
, -
- ,
- ;
articles.forEach(function(p){@
if(p.visible&
===y){ -
}else if(!p.visible&usefullp===null){
-
}
-
}); -
if(pp!==null&-
tttt ppisDrop();
- }else if(
-
.);res
}
}
- }
- tx =xjg 4*(P_半徑*2 X_J);
- }
- }
-
原理也不難,也跟上面畫背景差不多,是否查找所有點,然後根據當前時間的數字轉換成的字符串來判斷,當前點是否應該有像素,如果有像素就再判斷當前這個點已經有消費對像在了,如果已經有消費對像在了,就直接跳出不處理,如果沒有消費對像在,就再找一個沒有被使用的消費對象重置到這個位置。這一點是不應該有粉末的,但是卻有耳機,那就拿到這個耳機,讓這個耳機得到自由的落體。
- 時間設定也寫好了,就可以寫舞台更新的程式碼了:
- XML/HTML 程式碼
將內容複製到剪貼簿
-
var timeCount_0 = 0,timeCount_1 ,粒子 = [];
函數 initAnimate(){
-
for(var
- i=0=0=0=0
- =0=0=0
- =0
- =200
;i ){ -
var -
p 🎜>
articles.push(p);
}
-
timeCount_0 =
- timeCount_1
= drawBg();
- setTime(timeCount_0)
- 動畫();
- }
-
- 函數 animate(){
- ctx.clearRect(0,0,canvas.width,canvas.height);
- ctx.drawImage(bgcanvas,0,0);
-
var timeCount_2 =
新
-
if(timeCount_1-timeCount_0>=1000){
- setTime(timeCount_1);
- timeCount_0 = timeCount_1;
- }
-
- articles.forEach(function(p){
- if(p.visible){
- p.update((timeCount_2-timeCount_1)/70);
- p.paint();
- }
- });
-
-
timeCount_1 = time
- RAF(animate)
- }
-
在initAnimate進行動畫初始化,初始化也就是先實例化兩百個粒子物件放到粒子容器中保存起來,再更新時間戳,快取背景,設定當前時間,然後呼叫animate動畫循環主體開始動畫。
animate中的邏輯也很簡單了,取得時間戳,如果兩個時間戳之間的時間差大於或等於1秒,就進行setTime。而再下面的就是將粒子容器裡的所有視覺化的粒子進行遍歷循環重繪了。
然後就做好啦:
個效果還是有很多可以優化的地方的,因為時鐘和分鐘都是動的比較少的,所以可以把這兩個緩存起來,當沒有動作的時候就直接將緩存數據畫上去就行了,這樣就可以減少舞台每一幀的繪圖API呼叫量,一定是能提升效能的。不過現在畢竟粒子不多,兩三百個粒子物件就夠用了,如果不去做優化,動畫還是能很流暢的運行的。所以樓主就偷個小懶吧。
原始碼位址:
https://github.com/whxaxes/canvas-test/blob/gh-pages/src/Funny-demo/coolClock/index.html