Hello,你們好!javascript
小W復活啦!繼續歡樂的給你們更博,輸送新知識~~java
不開玩笑啦!秒進正題~~~git
上次更博,小W給你們介紹了Canvas畫布的基礎部分,以及實現了一個由7*10點陣圖顯示的倒計時的基本架構。canvas
上次的效果以下圖所示,僅僅只是一個時間的靜態顯示而已:瀏覽器
今天呢,小W想實現就是,讓它開始倒計時!效果先給你們看一下:數據結構
Canvas畫布用於圖形的繪製、動畫,都是經過腳本(JavaScript)實現的。架構
上次更博,countdown.js代碼中,已經實現了時:分:秒的基本架構,先把上次的JS代碼再次梳理一下,在這個基礎上,小W再進行接下來的操做:函數
// 全局變量 有助於後期數據的變更更改 var WINDOW_WIDTH = 1024; var WINDOW_HEIGHT = 768; // 此處須要注意寬高的比例 適當縮小放大畫布的時候,儘可能同時縮小放大,避免出現圓形顯示爲橢圓形等不對稱現象 var MARGIN_LEFT = 30; var MARGIN_TOP = 60; var RADIUS = 8; window.onload = function(){ var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); canvas.width = WINDOW_WIDTH; canvas.height = WINDOW_HEIGHT; render( context ); } function render( cxt ){ var hours = 12; var minute = 36; var second = 59; // 小時 爲了顯示效果好看、設置居中,給每一個數字設置margin renderDigit( MARGIN_LEFT , MARGIN_TOP , parseInt(hours/10) , cxt ); // 每一個字水平點陣個數爲直徑7,半徑:7*2 = 14,14+1 = 15 (1間隔) renderDigit( MARGIN_LEFT + 15*(RADIUS+1) , MARGIN_TOP , parseInt(hours%10) , cxt ); // 冒號 (4*2+1)= 9 digit.js中 10表明 : renderDigit( MARGIN_LEFT+ 30*(RADIUS+1) , MARGIN_TOP , 10 , cxt ); // 分鐘 renderDigit( MARGIN_LEFT+ 39*(RADIUS+1) , MARGIN_TOP , parseInt(minute/10) , cxt ); renderDigit( MARGIN_LEFT+ 54*(RADIUS+1) , MARGIN_TOP , parseInt(minute%10) , cxt ); renderDigit( MARGIN_LEFT+ 69*(RADIUS+1) , MARGIN_TOP , 10 , cxt ); // 秒 renderDigit( MARGIN_LEFT+ 78*(RADIUS+1) , MARGIN_TOP , parseInt(second/10) , cxt ); renderDigit( MARGIN_LEFT+ 93*(RADIUS+1) , MARGIN_TOP , parseInt(second%10) , cxt ); } function renderDigit(x , y , num , cxt){ // X軸座標、Y軸座標、將要顯示的數字、canvas上下文語境
cxt.fillStyle = "#005588";
for (var i = 0 ; i < digit[num].length ;i++) {
for (var j = 0 ; j < digit[num][i].length ;j++){
if(digit[num][i][j] == 1){ cxt.beginPath();
// 圓心位置公式
cxt.arc( x+j * 2 * (RADIUS+1) + (RADIUS+1) , y+i * 2 * (RADIUS+1) + (RADIUS+1) , RADIUS , 0 , 2*Math.PI ); cxt.closePath(); cxt.fill();
}
}
}
}
梳理完成以後咱們能夠進行下一步操做了,首先,咱們須要設置一個截止時間,倒計時就是從如今開始到截止時間所剩餘的時間:學習
//限制: 小時二位數 不超過4天
var endTime = new Date(2017,9,15,18,15,26); // 注意!!!:data中的參數第二個表示月份,是由0-11表示的。0 - 一月;11- 十二月
這裏須要注意,咱們在以前調取小時hours的位數的時候,僅僅只是設置了兩位數,於是如今咱們的倒計時最多到99:99:99,也就是四天。若是有讀者須要實現更長時間的倒計時,須要再作些許調整,爲了效果美觀整潔,咱們這裏只設置兩位數。使用JS提供的data()方式設置截止時間。動畫
在render函數中,如何獲取當前時間距離截止時間剩餘時間?
JS的data對象給咱們提供了一個getTime的方法:它返回了距離1970.1.1的00:00:00的毫秒數,用這個方法減去截止日期的getTime(),這個差值就表示中間咱們須要倒計時的小時、分鐘和秒數,可是因爲時間是一秒一秒變更的,這個動畫效果須要不斷的與當前時間做比較,爲此咱們設計一個全局的變量,來表示如今倒計時須要多少秒?
var curShowTimeSecond = 0; // 如今倒計時須要多少毫秒, —— > 秒
接下來,對 curShowTimeSecond 進行具體的計算:
curShowTimeSecond = getCurShowTimeSecond(); // 封裝一個函數
// javascript Date 提供了 getTime 函數 以便於獲取實時時間 // getCurShowTimeSecond 函數 獲取當前總共的毫秒數 function getCurShowTimeSecond(){ var curTime = new Date(); // 獲取當前的時間是多少 var ret = endTime.getTime() - curTime.getTime(); //ret 獲取截止時間與當前時間相差的毫秒數 ret = Math.round( ret/1000 ); // 將毫秒轉換成秒 return ret>=0 ? ret : 0; // 判斷 ret,倒計時結束,函數返回0. }
如今,剩餘時間的秒數已經獲得了,咱們接下來須要設置小時、分鐘、秒數的顯示:
var hours = parseInt( curShowTimeSecond/3600 ); // 剩餘時間有多少個小時 var minute = parseInt( (curShowTimeSecond - hours * 3600) / 60 ); // 減去小時,剩餘時間的分鐘數 var second = curShowTimeSecond % 60; // 減去小時、分鐘後,剩餘時間還剩多少秒
到這裏,在瀏覽器的刷新後,倒計時能夠實現實時更新了。
然而咱們想要實現的是讓它本身更新、變化,實現倒計時,接下來咱們須要引入一個實現動畫的基礎函數——定時器setInterval() 方法:
// 動畫效果 setInterval( function(){ render( context ); // 繪製當前的畫面。 update(); // 根據繪製畫面所須要的數據結構,對數據結構進行調整。 }, 50 // 毫秒 );
其實,咱們能夠直接獲取新的時間在render()裏面進行繪製就能夠了,可是這個最終的效果是想要實現,隨着時間變化,產生彩色小球的物理變化的動畫,由於爲了鋪墊後文,咱們使用了一個update() 函數,以下圖所示:
// 時間更新函數 function update(){ // 注意 render 裏面是繪製curShowTimeSecond var nextShowTimeSecond = getCurShowTimeSecond(); // 下一次 // 下一次要顯示的時間(時\分\秒分解) var nextHours = parseInt( nextShowTimeSecond/3600 ); var nextMinute = parseInt( (nextShowTimeSecond - nextHours * 3600) / 60 ); var nextSecond = nextShowTimeSecond % 60; var curtHours = parseInt( curShowTimeSecond/3600 ); var curtMinute = parseInt( (curShowTimeSecond - curtHours * 3600) / 60 ); var curtSecond = curShowTimeSecond % 60; if(nextSecond != curtSecond) // 下一次顯示的秒數不等於當前顯示的秒數了,替換爲新的時間 curShowTimeSecond = nextShowTimeSecond; }
爲了不當前新圖像,與以前的圖像疊加,咱們在render()裏面引入一個新的函數:
// 爲避免新一次的圖像與以前的圖像疊加。 // clearRect(): 對一個矩形空間內的圖像進行一次刷新操做。這裏,對整個屏幕進行一次操做、刷新。 cxt.clearRect(0,0,WINDOW_WIDTH,WINDOW_HEIGHT);
到這裏咱們今天的效果已經基本實現了。
後續學習後,還會繼續更新,與你們分享...但願能夠多多關注!
若是有任何問題,你們能夠提出來,小W同你們一塊兒解決,有何不妥的地方也請大神多多指教,此次的博文就到這了,謝謝你們!
附完整countdown.js代碼
var WINDOW_WIDTH = 1024; var WINDOW_HEIGHT = 768; var MARGIN_LEFT = 30; var MARGIN_TOP = 60; var RADIUS = 8; //限制: 小時二位數 不超過4天 var endTime = new Date(2017,9,15,18,15,26); // 注意!!!:data中的參數第二個表示月份,是由0-11表示的。0 - 一月;11- 十二月 var curShowTimeSecond = 0; // 如今倒計時須要多少毫秒 window.onload = function(){ var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); canvas.width = WINDOW_WIDTH; canvas.height = WINDOW_HEIGHT; curShowTimeSecond = getCurShowTimeSecond(); //curShowTimeSecond:當前總共的毫秒數 // 動畫效果 setInterval( function(){ render( context ); update(); }, 50 // 毫秒 ); } // javascript 的 Date 提供了 getTime 函數 以便於獲取實時時間 // getCurShowTimeSecond 函數 獲取當前總共的毫秒數 function getCurShowTimeSecond(){ var curTime = new Date(); // 獲取當前的時間是多少 var ret = endTime.getTime() - curTime.getTime(); //ret 獲取截止時間與當前時間相差的毫秒數 ret = Math.round( ret/1000 ); // 將毫秒轉換成秒 return ret>=0 ? ret : 0; // 判斷 ret,倒計時結束,函數返回0. } // 時間更新函數 function update(){ var nextShowTimeSecond = getCurShowTimeSecond(); // 下一次要顯示的時間(時分秒分解) var nextHours = parseInt( nextShowTimeSecond/3600 ); var nextMinute = parseInt( (nextShowTimeSecond - nextHours * 3600) / 60 ); var nextSecond = nextShowTimeSecond % 60; var curtHours = parseInt( curShowTimeSecond/3600 ); // 一共須要多少個小時 var curtMinute = parseInt( (curShowTimeSecond - curtHours * 3600) / 60 ); var curtSecond = curShowTimeSecond % 60; if(nextSecond != curtSecond) curShowTimeSecond = nextShowTimeSecond; } function render( cxt ){ // 爲避免新一次的圖像與以前的圖像疊加。 // clearRect(): 對一個矩形空間內的圖像進行一次刷新操做。這裏,對整個屏幕進行一次刷新。 cxt.clearRect(0,0,WINDOW_WIDTH,WINDOW_HEIGHT); var hours = parseInt( curShowTimeSecond/3600 ); // 一共須要多少個小時 var minute = parseInt( (curShowTimeSecond - hours * 3600) / 60 ); var second = curShowTimeSecond % 60; // 小時 renderDigit( MARGIN_LEFT , MARGIN_TOP , parseInt(hours/10) , cxt ); // 每一個字水平位置直徑7,7*2 = 14半徑+1 = 15 renderDigit( MARGIN_LEFT + 15*(RADIUS+1) , MARGIN_TOP , parseInt(hours%10) , cxt ); // 冒號 (4*2+1)= 9 digit.js中 10表明 : renderDigit( MARGIN_LEFT+ 30*(RADIUS+1) , MARGIN_TOP , 10 , cxt ); // 分鐘 renderDigit( MARGIN_LEFT+ 39*(RADIUS+1) , MARGIN_TOP , parseInt(minute/10) , cxt ); renderDigit( MARGIN_LEFT+ 54*(RADIUS+1) , MARGIN_TOP , parseInt(minute%10) , cxt ); // 冒號 (4*2+1)= 9 digit.js中 10表明 : renderDigit( MARGIN_LEFT+ 69*(RADIUS+1) , MARGIN_TOP , 10 , cxt ); // 秒 renderDigit( MARGIN_LEFT+ 78*(RADIUS+1) , MARGIN_TOP , parseInt(second/10) , cxt ); renderDigit( MARGIN_LEFT+ 93*(RADIUS+1) , MARGIN_TOP , parseInt(second%10) , cxt ); } function renderDigit(x , y , num , cxt){ cxt.fillStyle = "#005588"; for (var i = 0 ; i < digit[num].length ;i++) { for (var j = 0 ; j < digit[num][i].length ;j++){ if(digit[num][i][j] == 1){ cxt.beginPath(); // 圓心位置公式 cxt.arc( x+j * 2 * (RADIUS+1) + (RADIUS+1) , y+i * 2 * (RADIUS+1) + (RADIUS+1) , RADIUS , 0 , 2*Math.PI ); cxt.closePath(); cxt.fill(); } } } }