基于Canvas的Html5多時區(qū)動態(tài)時鐘實戰(zhàn)代碼
前言
出差旅行相信大家一定會住酒店,大家在酒店的前臺進行預訂的時候,是不是都會留意。通常在大堂的前方會有一面時鐘,大概是下面這種樣子:

這里只是一個截圖,其實不太完整。上面詳細的羅列了巴黎、北京、紐約、倫敦、莫斯科、東京等城市的時間。 通常來說,之所以要展示這么多的時鐘,一般是對外的酒店,所面向的客人很多都是外國人,他們來自于四面八方,需要將時間和自己國家的時間一致,也是對時間同步的一種保障,這是一種服務力的體現(xiàn)。

當然,上面這種是實體的鐘,需要實體鐘表的采購成本?,F(xiàn)在電子屏已經很常見也很普及,那么有沒有可能將Web界面投放到電子屏中,實現(xiàn)電子鐘的web化展示,加上前端的樣式控制,應該也是可以滿足酒店等場所的顯示需求。也因此有了本文和相關的程序設計。
本文即以Canvas為基礎,以支持多時區(qū)的多時鐘的動態(tài)Web展示為例。實現(xiàn)一種在Html5上的電子鐘展示方法,首先介紹Canvas是什么,然后具體介紹如何進行時鐘的繪制,其次介紹時鐘的多時區(qū)支持,最后給出運行的實際效果。通過本文可以了解Canvas的詳細用法,掌握基本的文本繪制、樣式控制、屬性管理的基本知識,通過多時鐘的展示場景,將各個知識點融會貫通。如果您想了解Canvas的使用方法,可以來這里看看,有什么疑問的也可以在評論區(qū)留言交流。
一、關于Canvas技術
雖然Canvas不是最新的技術,相信很多朋友也不是很熟悉,因此本節(jié)還是花一點時間簡單的將Canvas的知識做個介紹,讓大家有個基本的了解,為下一節(jié)內容的講解打下基礎。主要包含三個部分,首先介紹canvas是什么,然后介紹它的語法。更詳細的內容,大家可以去看html的教程,上面有詳細的描述。
1、Canvas是什么
Canvas API(畫布)是在HTML5中新增的標簽用于在網頁實時生成圖像,并且可以操作圖像內容,基本上它是一個可以用JavaScript操作的位圖(bitmap)。Canvas 對象表示一個 HTML 畫布元素 -<canvas>。<canvas> 標記由 Apple 在 Safari 1.3 Web 瀏覽器中引入。對 HTML 的這一根本擴展的原因在于,HTML 在 Safari 中的繪圖能力也為 Mac OS X 桌面的 Dashboard 組件所使用,并且 Apple 希望有一種方式在 Dashboard 中支持腳本化的圖形。Firefox 1.5 和 Opera 9 都跟隨了 Safari 的引領。這兩個瀏覽器都支持 <canvas> 標記。我們甚至可以在 IE 中使用 <canvas> 標記,并在 IE 的 VML 支持的基礎上用開源的 JavaScript 代碼(由 Google 發(fā)起)來構建兼容性的畫布。<canvas> 的標準化的努力由一個 Web 瀏覽器廠商的非正式協(xié)會在推進, <canvas> 已經成為 HTML 5 草案中一個正式的標簽。
在現(xiàn)代 Web 開發(fā)中,開發(fā)者們更多的會借助 Canvas 提供的API去繪制上下文,可以自由繪制各種2D和3D圖形,創(chuàng)建富有視覺沖擊力的游戲場景和角色。Canvas的使用可以使得游戲能夠實現(xiàn)流暢的動態(tài)效果和用戶交互。無論是簡單的小游戲還是復雜的游戲引擎,Canvas 都被廣泛應用。
在WebGIS開發(fā)當中,canvas也是一個非常重要的展示場景,比如我們之前用過的動態(tài)標繪組件,也是基于Canvas來實現(xiàn)的,它的性能是非常高的。不管是面向2D還是3D的場景,canvas都有用武之地。
2、Canvas的屬性及渲染特性
Canvas的屬性比較簡單,而且它的屬性比較簡單,跟普通的Html標簽的屬性是一致的,也可以使用如ID、高度和寬度這幾個屬性。其作用就不再贅述,比較簡單。canvas的強大還是取決于它的渲染特性,因此這里簡單介紹一下Canvas的渲染特性。
說高性能渲染時得說說DOM駐留模式和Canvas快速模式。
DOM駐留模式:一種基于文檔對象模型(DOM)的渲染技術。在DOM駐留模式下,頁面的布局和樣式是由DOM樹來掌管的。當頁面需要更新時,瀏覽器會重新計算布局和樣式并重新渲染。此模式非常靈活,特別適用于處理動態(tài)頁面交互和多樣化的樣式控制。
Canvas快速模式:利用HTML5的Canvas元素進行圖形渲染。開發(fā)者可以使用Canvas提供的2D或3D繪圖API直接在畫布上繪制圖形。相比于DOM駐留模式,Canvas快速模式更加高效。它不關心頁面的布局和樣式,而是在需要時只重繪受影響的部分。
分層提高Canvas性能:可以進一步提升Canvas性能的策略,即對變化較少和變化較多的內容進行分開渲染。它能夠顯著降低完全沒有必要的渲染性能開銷。分層渲染的思想被廣泛應用于各種圖形相關的領域,從古老的皮影戲、套色印刷術,到現(xiàn)代電影/游戲工業(yè)以及虛擬現(xiàn)實領域等等。
上面簡單的對Canvas的相關知識進行簡單介紹,有了上述的基本知識,下面結合實例講解Canvas的多時區(qū)時鐘動態(tài)展示。
二、Canvas動態(tài)多時區(qū)展示
在了解Canvas的基本知識以后,我們來介紹Canvas的基本使用。在這個實例中,我們需要在Html5頁面中,使用Canvas繪制6個不同城市的時鐘,并且要在時鐘上標注是屬于哪個城市,其對應的24小時制時間是多少,同時時鐘要可以動態(tài)轉動。本節(jié)即以詳細代碼的形式進行講解。
1、新建html頁面
Canvas也是建立在Html頁面上的組件,因此想要把Canvas渲染出來,就一定要創(chuàng)建展示的基礎。新建一個html文件,關鍵代碼如下所示:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Canvas 多時區(qū)時鐘可視化</title>
<style>
body {
background-color: #F5F5F5;
}
canvas {
border: 1px dashed #444;
}
</style>
</head>
<body>
<table style="width:99%;margin: auto;align:center;">
<tbody>
<tr>
<td >
<canvas id="clock0" width="300" height="300"></canvas>
</td>
<td>
<canvas id="clock1" width="300" height="300"></canvas>
</td>
<td>
<canvas id="clock2" width="300" height="300"></canvas>
</td>
</tr>
<tr>
<td>
<canvas id="clock3" width="300" height="300"></canvas>
</td>
<td>
<canvas id="clock4" width="300" height="300"></canvas>
</td>
<td>
<canvas id="clock5" width="300" height="300"></canvas>
</td>
</tr>
</tbody>
</table>
</body>
</html>這里僅展示Canvas的功能API,對于頁面的特效樣式沒有做過多的設置,如果是真實項目,建議在這個基礎上狠狠地記性樣式的修改,改造成符合項目需要的美觀的。上面采用table布局,為了展示6個不同城市的時鐘,我們使用兩行三列的布局模式,每個單元格展示一個時鐘。為了實現(xiàn)動態(tài)的控制這些時鐘,比如第一個時鐘用來顯示紐約的時間,因此有必要使用id對每個canvas進行分別定義。
2、創(chuàng)建Canvas對象
在創(chuàng)建了html頁面展示元素之后,我們還需要使用canvas來繪制時鐘的效果,為了能實現(xiàn)時鐘的動態(tài)效果,我們將canvas的id屬性從0-5分別設置為clock0-clock5,分別用來代表"紐約","倫敦","巴黎","莫斯科","北京","東京"這五個不同時區(qū)的城市。為了在后面的時間繪制中能精準控制,我們將所有的Canvas創(chuàng)建出來之后,設置到對應的數(shù)組當中。
//創(chuàng)建時鐘數(shù)組
var clockArray = new Array();
var timeZoneArray = ["紐約","倫敦","巴黎","莫斯科","北京","東京"];
for(var i = 0;i < 6; i++){
const canvas = document.getElementById("clock" + i);
const ctx = canvas.getContext("2d");
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
// 將坐標系移動到中心點
ctx.translate(centerX, centerY);
clockArray.push(canvas);
}3、繪制所有的時鐘
將Canvas創(chuàng)建出來后,就可以進行時鐘的繪制了。下面將結合源碼來詳細介紹如何進行時鐘的繪制。
function drawClock() {
const now = new Date();
for(var j = 0;j < 6;j++){
var _canvas = clockArray[j];
var _ctx = _canvas.getContext("2d");
const radius = _canvas.width / 2 - 5;
const centerX = _canvas.width / 2;
const centerY = _canvas.height / 2;
_ctx.clearRect(-centerX, -centerY, _canvas.width, _canvas.height); // 每次繪制前清空整個畫布
_ctx.beginPath();
_ctx.arc(0, 0, radius, 0, 2 * Math.PI);
_ctx.stroke();
// 繪制鐘表數(shù)字
_ctx.textAlign = "center";
_ctx.textBaseline = "middle";
_ctx.font = "20px sans-serif";
var text = timeZoneArray[j];
_ctx.strokeText(text + "時間", 2, - 80);
_ctx.font = "bold 14px Arial";
drawClockNumber(_ctx,radius);//繪制數(shù)字
// 繪制時針
var bjHour = now.getHours();
//獲取小時
var hour = getHour(j,bjHour);
var minute = now.getMinutes();
var second = now.getSeconds();
drawShowTime(_ctx,hour,minute,second);//繪制當前時間
var hourAngle = (hour % 12 + minute / 60 + second / 3600) * Math.PI / 6;
var hourLength = 0.6 * radius;
var hourX = Math.sin(hourAngle) * hourLength;
var hourY = -Math.cos(hourAngle) * hourLength;
_ctx.beginPath();
_ctx.moveTo(0, 0);
_ctx.lineTo(hourX, hourY);
_ctx.lineWidth = 4;
_ctx.lineCap = "round";
_ctx.stroke();
// 繪制分針
const minuteAngle = (minute + second / 60) * Math.PI / 30;
const minuteLength = 0.8 * radius;
const minuteX = Math.sin(minuteAngle) * minuteLength;
const minuteY = -Math.cos(minuteAngle) * minuteLength;
_ctx.beginPath();
_ctx.moveTo(0, 0);
_ctx.lineTo(minuteX, minuteY);
_ctx.lineWidth = 2;
_ctx.stroke();
// 繪制秒針
const secondAngle = second * Math.PI / 30;
const secondLength = 0.9 * radius;
const secondX = Math.sin(secondAngle) * secondLength;
const secondY = -Math.cos(secondAngle) * secondLength;
drawScale(_ctx,radius);//繪制刻度
_ctx.beginPath();
_ctx.moveTo(0, 0);
_ctx.lineTo(secondX, secondY);
_ctx.lineWidth = 1;
_ctx.strokeStyle = "red"; // 設置顏色
_ctx.stroke();
// 繪制中央圓點
_ctx.beginPath();
_ctx.arc(0, 0, 5, 0, 2 * Math.PI);
_ctx.fillStyle = "#333"; // 設置顏色
_ctx.fill();
}
// 循環(huán)繪制
setTimeout(drawClock, 1000);
}上面的代碼非常詳細的給出了時鐘的展示過程,下面將繪制的步驟進行了簡單的介紹。
首先獲取canvas對象,并且清空畫布,因為時鐘每隔一秒即變化,同時分針秒針都要發(fā)生不斷地變化,這些就像橡皮擦一樣,要不斷擦除和不斷重新繪制。

然后在表盤中繪制具體是什么時間,比如北京時間,繪制后如下圖所示:

接下來就是繪制時鐘的數(shù)字刻度,比如1到12這幾個數(shù)字,如下圖所示:

//繪制刻度
function drawClockNumber(_ctx,radius){
for (let i = 1; i <= 12; i++) {
var angle = i * Math.PI / 6;
_ctx.rotate(angle);
_ctx.translate(0, -radius + 15);
_ctx.rotate(-angle);
_ctx.fillText(i.toString(), 0, 0);
_ctx.rotate(angle);
_ctx.translate(0, radius - 15);
_ctx.rotate(-angle)
}
}
繪制刻度的具體代碼:
// 繪制刻度
function drawScale(_ctx,radius){
// 假設最大刻度線長度是半徑的5%
const maxMajorTickLength = radius * 0.05; // 較大刻度線長度
const maxMinorTickLength = radius * 0.025; // 較小刻度線長度
for (let m = 0; m < 60; m++) {
// 計算每個刻度的角度
const minuteAngle = m * Math.PI / 30;
// 根據(jù)分鐘數(shù)決定刻度線的長度
let tickLength;
if (m % 5 === 0) {
// 如果是每5分鐘的刻度,使用較大刻度線長度
tickLength = maxMajorTickLength;
} else {
// 否則使用較小刻度線長度
tickLength = maxMinorTickLength;
}
// 計算刻度線端點的坐標
var x1 = Math.sin(minuteAngle) * radius; // 圓邊緣的x坐標
var y1 = -Math.cos(minuteAngle) * radius; // 圓邊緣的y坐標
var x2 = Math.sin(minuteAngle) * (radius - tickLength); // 刻度線端點的x坐標
var y2 = -Math.cos(minuteAngle) * (radius - tickLength); // 刻度線端點的y坐標
// 繪制刻度線
_ctx.beginPath();
_ctx.moveTo(x1, y1); // 從圓邊緣開始
_ctx.lineTo(x2, y2); // 向內延伸到刻度線端點
_ctx.stroke();
}
}在繪制刻度的這里,我剛開始一直沒成功,主要原因是沒掌握方法,刻度的兩個起始點沒繪制準確,因此導致了刻度繪制一直不準確,請記得一定計算好位置,尤其是使用moveTo和lineTo兩個方法類調整,主要刻度從圓邊緣開始,而不要movoTo(0,0),這樣從圓心開始,繪制出來的效果就不對了。
由于這6個城市分別屬于6個不同的時區(qū),因此也就造成了這6個城市的時間是不一樣的,也就是我們常說的時差,通過查找資料可以知道,這里每個城市的時差大約是如下代碼表示的。
function getHour(index,bjHour){
var hour = bjHour; // bjHour是北京時間的小時數(shù)
var offset; // 定義時區(qū)偏移量
// 根據(jù)時區(qū)索引計算偏移量
switch(index) {
case 0: // 紐約 (北京時間比紐約快13小時)
offset = -13;
break;
case 1: // 倫敦 (北京時間比倫敦快8小時)
offset = -8;
break;
case 2: // 巴黎 (北京時間比巴黎快7小時)
offset = -7;
break;
case 3: // 莫斯科 (北京時間比莫斯科快5小時)
offset = -5;
break;
case 4: // 北京 (默認為北京時間)
offset = 0;
break;
case 5: // 東京 (假設北京時間比東京慢1小時)
offset = 1;
break;
default: // 如果索引不在預期范圍內,返回原始小時數(shù)
return hour;
}
// 應用時區(qū)偏移量,并確保小時數(shù)在0到23之間
hour += offset;
hour = (hour + 24) % 24; // 循環(huán)處理,確保結果在24小時制內
return hour;
}這里通過計算偏移量的方式來計算城市的時間,剛開始沒有注意,這樣計算出來的結果,會有不準確,因此才采用了時區(qū)偏移的處理方式,這樣出來能保證每個時鐘都是24小時之內。當然,為了計算方便,您也可以直接使用我上面的轉換邏,是可以直接使用的。
經過上面的代碼,就可以實現(xiàn)時鐘的動態(tài)展示。效果如下所示:

總結
以上就是本文的主要內容,本文以Canvas為基礎,支持多時區(qū)的多時鐘的動態(tài)Web展示為例實現(xiàn)一種在Html5上的電子鐘展示方法,首先介紹Canvas是什么,然后具體介紹如何進行時鐘的繪制,其次介紹時鐘的多時區(qū)支持,最后給出運行的實際效果。通過本文可以了解Canvas的詳細用法,掌握基本的文本繪制、樣式控制、屬性管理的基本知識,通過多時鐘的展示場景,將各個知識點融會貫通。如果您想了解Canvas的使用方法,可以來這里看看。行文倉促,定有諸多不足之處,歡迎各位專家朋友有什么疑問的也可以在評論區(qū)留言交流。
為方便朋友們學習,源碼已經上傳至資源,大家可以下載:源碼傳送地址。
到此這篇關于基于Canvas的Html5多時區(qū)動態(tài)時鐘實戰(zhàn)的文章就介紹到這了,更多相關html5 canvas時鐘內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持腳本之家!
相關文章

HTML5 Canvas 實現(xiàn)在線簽字功能(示例代碼)
在現(xiàn)代互聯(lián)網應用中,有時我們需要讓用戶在網頁上進行簽字操作,比如確認文件、填寫電子表格或者簽署合同,利用 HTML5 的 canvas 畫布,我們可以輕松地實現(xiàn)這一功能,為用2024-06-19
分時大盤回顧功能是一種用于分析股票行情的工具,本文就介紹一下HTML5 Canvas 繪制股市走勢圖,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習2023-04-25
HTML5 canvas實現(xiàn)的靜態(tài)循環(huán)滾動播放彈幕
這篇文章主要介紹了HTML5 canvas實現(xiàn)的靜態(tài)循環(huán)滾動播放彈幕,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來2021-01-05
Html5基于canvas實現(xiàn)電子簽名并生成PDF文檔
這篇文章主要介紹了Html5基于canvas實現(xiàn)電子簽名并生成PDF文檔,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編2020-12-07- 這篇文章主要介紹了Html5 canvas畫圖白板踩坑,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-06-01
- 這篇文章主要介紹了基于html5 canvas做批改作業(yè)的小插件的相關資料,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參2020-05-20

html5 canvas 實現(xiàn)光線沿不規(guī)則路徑運動
這篇文章主要介紹了html5 canvas 實現(xiàn)光線沿不規(guī)則路徑運動,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-04-20
這篇文章主要介紹了HTML5 Canvas實現(xiàn)放大鏡效果示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習2020-03-25
Html5 Canvas實現(xiàn)圖片標記、縮放、移動和保存歷史狀態(tài)功能 (附轉換公
這篇文章主要介紹了Html5 Canvas實現(xiàn)圖片標記、縮放、移動和保存歷史狀態(tài)功能 (附轉換公式),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借2020-03-18- 這篇文章主要介紹了詳解HTML5 Canvas標簽及基本使用,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2020-01-10





