更新——Canvas画布动画效果之实现倒计时
Hello,大家好!
小W復(fù)活啦!繼續(xù)歡樂的給大家更博,輸送新知識(shí)~~
不開玩笑啦!秒進(jìn)正題~~~
上次更博,小W給大家介紹了Canvas畫布的基礎(chǔ)部分,以及實(shí)現(xiàn)了一個(gè)由7*10點(diǎn)陣圖顯示的倒計(jì)時(shí)的基本架構(gòu)。
上次的效果如下圖所示,僅僅只是一個(gè)時(shí)間的靜態(tài)顯示而已:
今天呢,小W想實(shí)現(xiàn)就是,讓它開始倒計(jì)時(shí)!效果先給大家看一下:
Canvas畫布用于圖形的繪制、動(dòng)畫,都是通過腳本(JavaScript)實(shí)現(xiàn)的。
上次更博,countdown.js代碼中,已經(jīng)實(shí)現(xiàn)了時(shí):分:秒的基本架構(gòu),先把上次的JS代碼再次梳理一下,在這個(gè)基礎(chǔ)上,小W再進(jìn)行接下來的操作:
// 全局變量 有助于后期數(shù)據(jù)的變動(dòng)更改 var WINDOW_WIDTH = 1024; var WINDOW_HEIGHT = 768; // 此處需要注意寬高的比例 適當(dāng)縮小放大畫布的時(shí)候,盡量同時(shí)縮小放大,避免出現(xiàn)圓形顯示為橢圓形等不對(duì)稱現(xiàn)象 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;// 小時(shí) 為了顯示效果好看、設(shè)置居中,給每個(gè)數(shù)字設(shè)置marginrenderDigit( MARGIN_LEFT , MARGIN_TOP , parseInt(hours/10) , cxt ); // 每個(gè)字水平點(diǎn)陣個(gè)數(shù)為直徑7,半徑:7*2 = 14,14+1 = 15 (1間隔) renderDigit( MARGIN_LEFT + 15*(RADIUS+1) , MARGIN_TOP , parseInt(hours%10) , cxt );// 冒號(hào) (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軸坐標(biāo)、Y軸坐標(biāo)、將要顯示的數(shù)字、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();
}
}
}
}
梳理完成之后我們可以進(jìn)行下一步操作了,首先,我們需要設(shè)置一個(gè)截止時(shí)間,倒計(jì)時(shí)就是從現(xiàn)在開始到截止時(shí)間所剩余的時(shí)間:
//限制: 小時(shí)二位數(shù) 不超過4天 var endTime = new Date(2017,9,15,18,15,26); // 注意!!!:data中的參數(shù)第二個(gè)表示月份,是由0-11表示的。0 - 一月;11- 十二月這里需要注意,我們?cè)谥罢{(diào)取小時(shí)hours的位數(shù)的時(shí)候,僅僅只是設(shè)置了兩位數(shù),因而現(xiàn)在我們的倒計(jì)時(shí)最多到99:99:99,也就是四天。如果有讀者需要實(shí)現(xiàn)更長(zhǎng)時(shí)間的倒計(jì)時(shí),需要再做些許調(diào)整,為了效果美觀整潔,我們這里只設(shè)置兩位數(shù)。使用JS提供的data()方式設(shè)置截止時(shí)間。
在render函數(shù)中,如何獲取當(dāng)前時(shí)間距離截止時(shí)間剩余時(shí)間?
JS的data對(duì)象給我們提供了一個(gè)getTime的方法:它返回了距離1970.1.1的00:00:00的毫秒數(shù),用這個(gè)方法減去截止日期的getTime(),這個(gè)差值就表示中間我們需要倒計(jì)時(shí)的小時(shí)、分鐘和秒數(shù),但是由于時(shí)間是一秒一秒變動(dòng)的,這個(gè)動(dòng)畫效果需要不斷的與當(dāng)前時(shí)間作比較,為此我們?cè)O(shè)計(jì)一個(gè)全局的變量,來表示現(xiàn)在倒計(jì)時(shí)需要多少秒?
var curShowTimeSecond = 0; // 現(xiàn)在倒計(jì)時(shí)需要多少毫秒, —— > 秒接下來,對(duì) curShowTimeSecond 進(jìn)行具體的計(jì)算:
curShowTimeSecond = getCurShowTimeSecond(); // 封裝一個(gè)函數(shù) // javascript Date 提供了 getTime 函數(shù) 以便于獲取實(shí)時(shí)時(shí)間 // getCurShowTimeSecond 函數(shù) 獲取當(dāng)前總共的毫秒數(shù) function getCurShowTimeSecond(){var curTime = new Date(); // 獲取當(dāng)前的時(shí)間是多少var ret = endTime.getTime() - curTime.getTime(); //ret 獲取截止時(shí)間與當(dāng)前時(shí)間相差的毫秒數(shù)ret = Math.round( ret/1000 ); // 將毫秒轉(zhuǎn)換成秒return ret>=0 ? ret : 0; // 判斷 ret,倒計(jì)時(shí)結(jié)束,函數(shù)返回0. }現(xiàn)在,剩余時(shí)間的秒數(shù)已經(jīng)得到了,我們接下來需要設(shè)置小時(shí)、分鐘、秒數(shù)的顯示:
var hours = parseInt( curShowTimeSecond/3600 ); // 剩余時(shí)間有多少個(gè)小時(shí)var minute = parseInt( (curShowTimeSecond - hours * 3600) / 60 ); // 減去小時(shí),剩余時(shí)間的分鐘數(shù)var second = curShowTimeSecond % 60; // 減去小時(shí)、分鐘后,剩余時(shí)間還剩多少秒到這里,在瀏覽器的刷新后,倒計(jì)時(shí)可以實(shí)現(xiàn)實(shí)時(shí)更新了。
然而我們想要實(shí)現(xiàn)的是讓它自己更新、變化,實(shí)現(xiàn)倒計(jì)時(shí),接下來我們需要引入一個(gè)實(shí)現(xiàn)動(dòng)畫的基礎(chǔ)函數(shù)——定時(shí)器setInterval() 方法:
// 動(dòng)畫效果 setInterval(function(){render( context ); // 繪制當(dāng)前的畫面。update(); // 根據(jù)繪制畫面所需要的數(shù)據(jù)結(jié)構(gòu),對(duì)數(shù)據(jù)結(jié)構(gòu)進(jìn)行調(diào)整。},50 // 毫秒);其實(shí),我們可以直接獲取新的時(shí)間在render()里面進(jìn)行繪制就可以了,但是這個(gè)最終的效果是想要實(shí)現(xiàn),隨著時(shí)間變化,產(chǎn)生彩色小球的物理變化的動(dòng)畫,因?yàn)闉榱虽亯|后文,我們使用了一個(gè)update() 函數(shù),如下圖所示:
// 時(shí)間更新函數(shù) function update(){// 注意 render 里面是繪制curShowTimeSecond var nextShowTimeSecond = getCurShowTimeSecond(); // 下一次// 下一次要顯示的時(shí)間(時(shí)\分\秒分解) 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) // 下一次顯示的秒數(shù)不等于當(dāng)前顯示的秒數(shù)了,替換為新的時(shí)間curShowTimeSecond = nextShowTimeSecond; }
為了避免當(dāng)前新圖像,與之前的圖像疊加,我們?cè)趓ender()里面引入一個(gè)新的函數(shù):
// 為避免新一次的圖像與之前的圖像疊加。 // clearRect(): 對(duì)一個(gè)矩形空間內(nèi)的圖像進(jìn)行一次刷新操作。這里,對(duì)整個(gè)屏幕進(jìn)行一次操作、刷新。cxt.clearRect(0,0,WINDOW_WIDTH,WINDOW_HEIGHT);到這里我們今天的效果已經(jīng)基本實(shí)現(xiàn)了。
后續(xù)學(xué)習(xí)后,還會(huì)繼續(xù)更新,與大家分享...希望可以多多關(guān)注!
如果有任何問題,大家可以提出來,小W同大家一起解決,有何不妥的地方也請(qǐng)大神多多指教,這次的博文就到這了,謝謝大家!
?附完整countdown.js代碼?
var WINDOW_WIDTH = 1024; var WINDOW_HEIGHT = 768; var MARGIN_LEFT = 30; var MARGIN_TOP = 60; var RADIUS = 8;//限制: 小時(shí)二位數(shù) 不超過4天 var endTime = new Date(2017,9,15,18,15,26); // 注意!!!:data中的參數(shù)第二個(gè)表示月份,是由0-11表示的。0 - 一月;11- 十二月 var curShowTimeSecond = 0; // 現(xiàn)在倒計(jì)時(shí)需要多少毫秒 window.onload = function(){var canvas = document.getElementById("canvas");var context = canvas.getContext("2d");canvas.width = WINDOW_WIDTH;canvas.height = WINDOW_HEIGHT;curShowTimeSecond = getCurShowTimeSecond(); //curShowTimeSecond:當(dāng)前總共的毫秒數(shù)// 動(dòng)畫效果 setInterval(function(){render( context );update();},50 // 毫秒 );}// javascript 的 Date 提供了 getTime 函數(shù) 以便于獲取實(shí)時(shí)時(shí)間 // getCurShowTimeSecond 函數(shù) 獲取當(dāng)前總共的毫秒數(shù) function getCurShowTimeSecond(){var curTime = new Date(); // 獲取當(dāng)前的時(shí)間是多少var ret = endTime.getTime() - curTime.getTime(); //ret 獲取截止時(shí)間與當(dāng)前時(shí)間相差的毫秒數(shù)ret = Math.round( ret/1000 ); // 將毫秒轉(zhuǎn)換成秒return ret>=0 ? ret : 0; // 判斷 ret,倒計(jì)時(shí)結(jié)束,函數(shù)返回0. }// 時(shí)間更新函數(shù) function update(){var nextShowTimeSecond = getCurShowTimeSecond();// 下一次要顯示的時(shí)間(時(shí)分秒分解)var nextHours = parseInt( nextShowTimeSecond/3600 ); var nextMinute = parseInt( (nextShowTimeSecond - nextHours * 3600) / 60 ); var nextSecond = nextShowTimeSecond % 60;var curtHours = parseInt( curShowTimeSecond/3600 ); // 一共需要多少個(gè)小時(shí)var curtMinute = parseInt( (curShowTimeSecond - curtHours * 3600) / 60 ); var curtSecond = curShowTimeSecond % 60;if(nextSecond != curtSecond) curShowTimeSecond = nextShowTimeSecond;}function render( cxt ){// 為避免新一次的圖像與之前的圖像疊加。// clearRect(): 對(duì)一個(gè)矩形空間內(nèi)的圖像進(jìn)行一次刷新操作。這里,對(duì)整個(gè)屏幕進(jìn)行一次刷新。cxt.clearRect(0,0,WINDOW_WIDTH,WINDOW_HEIGHT);var hours = parseInt( curShowTimeSecond/3600 ); // 一共需要多少個(gè)小時(shí)var minute = parseInt( (curShowTimeSecond - hours * 3600) / 60 ); var second = curShowTimeSecond % 60;// 小時(shí)renderDigit( MARGIN_LEFT , MARGIN_TOP , parseInt(hours/10) , cxt ); // 每個(gè)字水平位置直徑7,7*2 = 14半徑+1 = 15 renderDigit( MARGIN_LEFT + 15*(RADIUS+1) , MARGIN_TOP , parseInt(hours%10) , cxt );// 冒號(hào) (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 );// 冒號(hào) (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(); } } } }?
轉(zhuǎn)載于:https://www.cnblogs.com/Tracey-1023/p/7667878.html
總結(jié)
以上是生活随笔為你收集整理的更新——Canvas画布动画效果之实现倒计时的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 基础面试 英文_[Java面试
- 下一篇: php字符串怎么传到html_php字符