首頁  >  文章  >  web前端  >  用HTML5製作數位時鐘的教學_html5教學技巧

用HTML5製作數位時鐘的教學_html5教學技巧

WBOY
WBOY原創
2016-05-16 15:46:352373瀏覽

2015511172231746.png (836×306)

就是這個數字時鐘,當時覺得這個創意不錯,但是也沒去折騰。直到昨天同事又在網路上看到這個案例,他覺得很酷炫,就跑過來問我,這個是怎麼實現的,然後我大概想了一下實現方法後也來了點興趣,就花了一點時間模仿做出來了一個。不同的是,岑安用的是div來做的。而我就是用canvas來實現的。用canvas來做性能方面會更好,因為就單單操控每個點的運動,用js控制dom的style屬性跟用js控制canvas繪圖相比性能方面肯定是有所欠缺的。

  先上個我做的DEMO吧,然後再簡述一下做這個的方法:   看DEMO請戳我 。

  做這個想法很簡單,就是透過字串保存各個數字的位置: 
複製程式碼

XML/HTML Code複製內容到剪貼簿
  1. var numData = [   
  2.             "1111/1001/1001/1001/1001/1001/1111", //0   🎠
  3.             "0001/0001/0001/0001/0001/0001/0001", //1   
  4.             "1111/0001/0001/1111/1000/1000/1111", //2   
  5. 🎠             "1111/0001/0001/1111/0001/0001/1111", //3   
  6. 🎠
  7.             "1010/1010/1010/1111/0010/0010/0010", //4   
  8.             "1111/1000/1000/1111/0001/0001/1111", //5   🎠
  9.             "1111/1000/1000/1111/1001/1001/1111", //6   
  10. 🎠             "1111/0001/0001/0001/0001/0001/0001", //7   
  11.             "1111/1001/1001/1111/1001/1001/1111", //8   🎠
  12.             "1111/1001/1001/1111/0001/0001/1111", //9   🎠
  13.             "0000/0000/0010/0000/0010/0000/0000", //:   
  14.         ]  
  15.   0代表沒像素,1代表有像素,/是為了更好看些,就是分行嘛,簡單說起來:比如0就是:   
  16. XML/HTML Code
複製內容到剪貼簿

        1  1  1  1   
  
  1.   1  0  0  1      
  2.   1  0  0  1   
  3.   
  4.   1  0  0  1   
  5.   
  6.   1  0  0  1   
  7.   
  8.   1  0  0  1   
  9.   
  10.   1  1  1  1     
  11. 這樣就很清楚了吧。從0到9還有一個:號都用字串表示好。

      接著就寫個粒子對象,也就是像素點:

    XML/HTML Code複製內容到剪貼簿
    1. var P_radius = 8,重力 = 9.8;   
    2.         var 粒子 =             this.x
    3.  = 0 = 0;   
    4.             this.y = 0 = 0
    5. ;                this.vx = 0
    6.  = 
    7. 00                this.vy
    8.  = 
    9. 0 = 0;   
    10.             
    11. this.color = " = " = 
    12. "   
    13.             this.visible =    
    14.             
    15. this.drop
    16.  =    
    17.         }   
    18.         
    19. Particle.prototype
    20.  = {   
    21.             建構子: 粒子,                paint:function(){        //螢光燈本身為   
    22.                 
    23. ctx.fillStyle
    24. ctx.fillStyle
    25. ctx.fillStyle
    26. ctx.fillStyle
    27. @                    ctx.beginPath();                    ctx.arc(this.x,this.y,P_radius,0,2*Math.PI);                    ctx.fill();                },   
    28.             reset:function(x,y,color){        //重設   
    29.                 this.x
    30.  = x;   
    31.                 this.y
    32.  = y;   
    33.                 this.vx >   
    34.                 
    35. this.vy =                     this.color
    36.   
    37.                 this.visible  this.visible
    38.   this.visible                     this.drop
    39.     
    40.             },                isDrop:function(){        //下對上   
    41.                 
    42. this.drop
    43.     
    44.                 var 
    45. vx = vx = vx =  🎜>
    46.                 this.vx 🎜> =0.5?             },   
    47.             update:function(time){        //每個上幀的動作   
    48.                 if(this.drop){   
    49.                     this.x = this.vx*時間;   
    50.                     this.y = this.vy*時間;   
    51.   
    52.                     var vy vy 
    53. vy 🎜>
    54.                        if(this.y>
    55. =canvas.height                         以 P_radius                             vy
    56.                     }      
    57.                     
    58. this.vy
    59.  = = = 
    60.   
    61.                  ‧ 🎜> canvas.width P_radius||this.y
    62. -P_radius
    63. ||this.y
    64. >
    65. height P_radius){                            將中對                     }                    }                }            }凡   
    66.    粒子物件的屬性比較簡單,就位置,速度,以及是否可視化。方法的話,paint是較差方法,reset是重置(因為粒子要循環利用的,提升性能),isDrop是粒子落下方法,update就是每一幀更新消耗品的動作,更新當消耗品運動超出畫布的稀疏區域時,將其視覺化設定為false,在消耗品容器中儲存起來等待下一次呼叫。 寫好物資對象後,需要考慮讓物資按照位置畫上去如何,同時當物資不需要時能夠讓他做自由落體的動畫了。 先畫背景(原來沒有像素的白點):
    67. XML/HTML 程式碼
    68. 將內容複製到剪貼簿
      1. 函數drawBg(){   
      2.             var tx = (canvas.width-(P_iusd*2*)jjg*   
      3.             for(var i=0=0=0
      4. =
      5. 0=0
      6. =
      7. 0=0=0=8;i ){   
      8.                 var ty = (canvasheight-((P_hius)yjah);                    for(var j
      9. =j= numData
      10. [0].length;j ){   
      11.                     var tt
      12.  tt tt tt
      13.                          if(tt==="/>tt
      14. ==="/
      15.                         ty =yjg;                        }其他 {                            var x (P_radius*2 X_J),   
      16.                             
      17. ;   
      18.                          
      19. bgctx.FillStyle

        ;   

      20.                         bgctx.beginPath();   
      21.                         bgctx.arc(x,y,P_radius,0,2*Math.PI);   
      22.                         bgctx.fill();   
      23.                     }   
      24.                 }   
                    tx =xjg 4*(P_半徑*2 X_J);                }            }   

      先把背景畫到一個離屏canvas中緩存起來,接下來每一幀重畫的時候就不需要邏輯計算了,直接把那個離屏canvas畫上去就行了。上面的邏輯應該不難理解,就是透過兩個循環,循環8個數字,然後再對每個數字一個點一個點進行繪製,當遇到“/”時,就說明要換行了,把繪製的ty加個換行間隔,再把tx重置,再進行繪製。就這樣,點就可以都畫出來了。效果圖如下:
    2015511172757389.png (1282×350)

    背景畫好了,就開始根據每一秒的時間,畫數字像素吧。方法主要是這個:

    XML/HTML Code複製內容到剪貼簿
    1. 函數 setTime(時間){   
    2.             var h =                 
    3.  = 
    4.  =  🎜>                 
    5. s
    6.  = s = 時間             
    7. hh             
    8.  =m             ss   
    9.             var nowdate = h ":" m ":" s;   
    10.             var tx
    11.  = (canvas.width-(P_ius)> >顏色 = "";                for(var 
    12. i=0=0=0=
    13. 0=0=0=0=0
    14. =nowdate.length;i ){                    var n
    15.  == nowdate.charAt(i)),   
    16.                     文字文字
    17. 文字
    18.   
    19.                 var ty
    20.   =
    21.   
    22.                 開關(i){   
    23.                     case 0:顏色                       case  break;   
    24.                     案例 3:顏色  
    25.                     案例 5:顏色                       案例 6:顏色
    26.   
    27.                 }      
    28.                 for(var 
    29. j
    30. =
    31. j
    32. =
    33. text.length;j ){                        var tt                     if(tt
    34. ==="/>tt==="/                         ty =yjg;                        }其他{   
    35.                         var x (P_radius*2 X_J),                                
    36. ,   
    37.                             
    38. ,   
    39.                             ;                            articles.forEach(function(p){@                              if(p.visible&
    40. ===y){   
    41.                                                               }else if(!p.visible&usefullp===null){   
    42.                                                                }   
    43.                       });   
    44.                         if(pp!==null&
    45. tttt                            ppisDrop();   
    46.                         }else if(
    47.                             .);res                             }                        }   
    48.                 }   
    49.                 tx =xjg 4*(P_半徑*2 X_J);   
    50.             }   
    51.         }  
    52. 原理也不難,也跟上面畫背景差不多,是否查找所有點,然後根據當前時間的數字轉換成的字符串來判斷,當前點是否應該有像素,如果有像素就再判斷當前這個點已經有消費對像在了,如果已經有消費對像在了,就直接跳出不處理,如果沒有消費對像在,就再找一個沒有被使用的消費對象重置到這個位置。這一點是不應該有粉末的,但是卻有耳機,那就拿到這個耳機,讓這個耳機得到自由的落體。
    53. 時間設定也寫好了,就可以寫舞台更新的程式碼了:
    54. XML/HTML 程式碼
    55. 將內容複製到剪貼簿
    1. var timeCount_0 = 0,timeCount_1 ,粒子 = [];            函數 initAnimate(){   
    2.             for(var 
    3. i=0=0=0=0
    4. =0=0=0
    5. =0
    6. =200
    7. ;i ){   
    8.                 var 
    9. p 🎜>                 articles.push(p);                }   
    10.                timeCount_0 = 
    11.             
    12. timeCount_1
    13.  =             drawBg();   
    14.             setTime(timeCount_0)   
    15.             動畫();   
    16.         }   
    17.   
    18.         函數 animate(){   
    19.             ctx.clearRect(0,0,canvas.width,canvas.height);   
    20.             ctx.drawImage(bgcanvas,0,0);   
    21.                var timeCount_2 = 
    22.   
    23.             if(timeCount_1-timeCount_0>=1000){   
    24.                 setTime(timeCount_1);   
    25.                 timeCount_0 = timeCount_1;   
    26.             }   
    27.   
    28.             articles.forEach(function(p){   
    29.                 if(p.visible){   
    30.                     p.update((timeCount_2-timeCount_1)/70);   
    31.                     p.paint();   
    32.                 }   
    33.             });   
    34.   
    35.             timeCount_1 = time   
    36.             RAF(animate)   
    37.         }  
    38.   在initAnimate進行動畫初始化,初始化也就是先實例化兩百個粒子物件放到粒子容器中保存起來,再更新時間戳,快取背景,設定當前時間,然後呼叫animate動畫循環主體開始動畫。
      animate中的邏輯也很簡單了,取得時間戳,如果兩個時間戳之間的時間差大於或等於1秒,就進行setTime。而再下面的就是將粒子容器裡的所有視覺化的粒子進行遍歷循環重繪了。
    然後就做好啦:


    個效果還是有很多可以優化的地方的,因為時鐘和分鐘都是動的比較少的,所以可以把這兩個緩存起來,當沒有動作的時候就直接將緩存數據畫上去就行了,這樣就可以減少舞台每一幀的繪圖API呼叫量,一定是能提升效能的。不過現在畢竟粒子不多,兩三百個粒子物件就夠用了,如果不去做優化,動畫還是能很流暢的運行的。所以樓主就偷個小懶吧。
    2015511172909169.png (1263×507)  原始碼位址:

    https://github.com/whxaxes/canvas-test/blob/gh-pages/src/Funny-demo/coolClock/index.html

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn