使用JavaScript實(shí)現(xiàn)一個(gè)炫酷的羅盤(pán)時(shí)鐘
前言
在探究前端動(dòng)畫(huà)時(shí)。想到之前在鎖屏壁紙看到的羅盤(pán)時(shí)鐘,看著很是炫酷,于是說(shuō)干就干,一起來(lái)研究下怎么用簡(jiǎn)單的方法實(shí)現(xiàn)這個(gè)炫酷的效果。 需要源碼的小伙伴可到文章結(jié)尾直接復(fù)制使用。
先上效果圖:
實(shí)現(xiàn)思路
(1)首先我們需要定義一系列的月、日、時(shí)、分、秒的數(shù)組,用來(lái)展示羅盤(pán)不同圓環(huán)上的數(shù)字
var monthText = ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]; var dayText = ["一日", "二日", "三日", "四日", "五日", "六日", "七日", "八日", "九日", "十日", "十一日", "十二日", "十三日", "十四日", "十五日", "十六日" , "十七日", "十八日", "十九日", "二十日", "二十一日", "二十二日", "二十三日", "二十四日", "二十五日", "二十六日", "二十七日", "二十八日", "二十九日", "三十日", "三十一日"]; var weekText = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]; var hourText = ["零時(shí)", "一時(shí)", "二時(shí)", "三時(shí)", "四時(shí)", "五時(shí)", "六時(shí)", "七時(shí)", "八時(shí)", "九時(shí)", "十時(shí)", "十一時(shí)", "十二時(shí)", "十三時(shí)", "十四時(shí)", "十五時(shí)", "十六時(shí)", "十七時(shí)", "十八時(shí)", "十九時(shí)", "二十時(shí)", "二十一時(shí)", "二十二時(shí)", "二十三時(shí)"]; ....
(2)通過(guò)循遍歷使用將這些數(shù)據(jù)生成dom節(jié)點(diǎn)放到html中
(3)通過(guò)setInterval
循環(huán)運(yùn)行,實(shí)時(shí)計(jì)算改變時(shí)分秒位置
開(kāi)始實(shí)現(xiàn)
(1)定義基礎(chǔ)dom結(jié)構(gòu)
<body> <div id="clock"></div> </body>
(2)循環(huán)遍歷已定義的月、日、時(shí)、分、秒數(shù)組,通過(guò)document.createElement
在clock下創(chuàng)建節(jié)點(diǎn),并將創(chuàng)建的節(jié)點(diǎn)保存到textSet
中,方便后面直接修改該dom的樣式。
//循環(huán)遍歷初始化數(shù)據(jù) function init() { clock = document.getElementById('clock'); for (var i = 0; i < textSet.length; i++) { for (var j = 0; j < textSet[i][0].length; j++) { var temp = createLabel(textSet[i][0][j]); clock.appendChild(temp); textSet[i][1].push(temp); } } clock.style.transform = "rotate(90deg)"; } //創(chuàng)建子節(jié)點(diǎn) function createLabel(text) { var div = document.createElement('div'); div.classList.add('label'); div.innerText = text; return div; }
(3)計(jì)算每一層每一個(gè)節(jié)點(diǎn)的位置,首先獲取當(dāng)前時(shí)間,為了保證當(dāng)前時(shí)間始終處于平行位置,所以需要計(jì)算其他值相對(duì)于當(dāng)前位置的偏移角度,以及他們相對(duì)的X、Y的位置。計(jì)算每一層圓半徑的長(zhǎng)度,通過(guò)Math.sin
和Math.cos
,以及獲取頁(yè)面寬和高定位到圓中心點(diǎn)就能得到每一個(gè)點(diǎn)的絕對(duì)位置。具體可以查看下面代碼解析。
function runTime() { //獲取當(dāng)前時(shí)間 var now = new Date(); var month = now.getMonth(); var day = now.getDate(); var week = now.getDay(); var hour = now.getHours(); var minute = now.getMinutes(); var seconds = now.getSeconds(); var nowValue = [month, day - 1, week, hour, minute, seconds]; initStyle(); //當(dāng)前年月日時(shí)高亮 for (var i = 0; i < nowValue.length; i++) { var num = nowValue[i]; textSet[i][1][num].style.color = '#fff'; } //計(jì)算圓中心位置 var widthMid = document.body.clientWidth / 2; var heightMid = document.body.clientHeight / 2; for (var i = 0; i < textSet.length; i++) { for (var j = 0; j < textSet[i][0].length; j++) { //計(jì)算每一層的圓半徑 var r = (i + 1) * 35 + 50 * i; //計(jì)算旋轉(zhuǎn)角度 var deg = 360 / textSet[i][1].length * (j - nowValue[i]); //計(jì)算絕對(duì)位置 var x = r * Math.sin(deg * Math.PI / 180) + widthMid; var y = heightMid - r * Math.cos(deg * Math.PI / 180); //改變每一個(gè)節(jié)點(diǎn)的位置 var temp = textSet[i][1][j]; temp.style.transform = 'rotate(' + (-90 + deg) + 'deg)'; temp.style.left = x + 'px'; temp.style.top = y + 'px'; } } } //還原所有的默認(rèn)樣式 function initStyle() { var label = document.getElementsByClassName('label'); for (var i = 0; i < label.length; i++) { label[i].style.color = '#4d4d4d'; } }
(4)定義每一個(gè)節(jié)點(diǎn)的基本樣式,為了實(shí)現(xiàn)時(shí)間變化時(shí)有旋轉(zhuǎn)效果,增加transition: left 1s, top 1s;
的過(guò)度動(dòng)畫(huà)
.label { position: absolute; display: inline-block; color: #4d4d4d; text-align: center; padding: 0 5px; font-family: "Microsoft YaHei"; font-size: 19px; font-weight: bolder; transition: left 1s, top 1s; transform-origin: 0% 0% }
完整代碼
附上全部代碼,有需要的小伙伴可直接復(fù)制使用:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>羅盤(pán)時(shí)鐘</title> <style type="text/css"> * { margin: 0; padding: 0 } html, body { width: 100%; height: 100%; background-color: black; overflow: hidden } #clock { position: relative; width: 100%; height: 100%; background: black } .label { position: absolute; display: inline-block; color: #4d4d4d; text-align: center; padding: 0 5px; font-family: "Microsoft YaHei"; font-size: 19px; font-weight: bolder; transition: left 1s, top 1s; transform-origin: 0% 0% } </style> <script type="text/javascript"> var monthText = ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]; var dayText = ["一日", "二日", "三日", "四日", "五日", "六日", "七日", "八日", "九日", "十日", "十一日", "十二日", "十三日", "十四日", "十五日", "十六日" , "十七日", "十八日", "十九日", "二十日", "二十一日", "二十二日", "二十三日", "二十四日", "二十五日", "二十六日", "二十七日", "二十八日", "二十九日", "三十日", "三十一日"]; var weekText = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]; var hourText = ["零時(shí)", "一時(shí)", "二時(shí)", "三時(shí)", "四時(shí)", "五時(shí)", "六時(shí)", "七時(shí)", "八時(shí)", "九時(shí)", "十時(shí)", "十一時(shí)", "十二時(shí)", "十三時(shí)", "十四時(shí)", "十五時(shí)", "十六時(shí)", "十七時(shí)", "十八時(shí)", "十九時(shí)", "二十時(shí)", "二十一時(shí)", "二十二時(shí)", "二十三時(shí)"]; var minuteText = ["零分", "一分", "二分", "三分", "四分", "五分", "六分", "七分", "八分", "九分", "十分", "十一分", "十二分", "十三分", "十四分", "十五分", "十六分", "十七分", "十八分", "十九分", "二十分", "二十一分", "二十二分", "二十三分", "二十四分", "二十五分", "二十六分", "二十七分", "二十八分", "二十九分", "三十分", "三十一分", "三十二分", "三十三分", "三十四分", "三十五分", "三十六分", "三十七分", "三十八分", "三十九分", "四十分", "四十一分", "四十二分", "四十三分", "四十四分", "四十五分", "四十六分", "四十七分", "四十八分", "四十九分", "五十分", "五十一分", "五十二分", "五十三分", "五十四分", "五十五分", "五十六分", "五十七分", "五十八分", "五十九分"]; var secondsText = ["零秒", "一秒", "二秒", "三秒", "四秒", "五秒", "六秒", "七秒", "八秒", "九秒", "十秒", "十一秒", "十二秒", "十三秒", "十四秒", "十五秒", "十六秒", "十七秒", "十八秒", "十九秒", "二十秒", "二十一秒", "二十二秒", "二十三秒", "二十四秒", "二十五秒", "二十六秒", "二十七秒", "二十八秒", "二十九秒", "三十秒", "三十一秒", "三十二秒", "三十三秒", "三十四秒", "三十五秒", "三十六秒", "三十七秒", "三十八秒", "三十九秒", "四十秒", "四十一秒", "四十二秒", "四十三秒", "四十四秒", "四十五秒", "四十六秒", "四十七秒", "四十八秒", "四十九秒", "五十秒", "五十一秒", "五十二秒", "五十三秒", "五十四秒", "五十五秒", "五十六秒", "五十七秒", "五十八秒", "五十九秒"]; var clock; var monthList = []; var dayList = []; var weekList = []; var hourList = []; var minuteList = []; var secondsList = []; var textSet = [[monthText, monthList], [dayText, dayList], [weekText, weekList], [hourText, hourList], [minuteText, minuteList], [secondsText, secondsList]]; var labelX = []; var labelY = []; window.onload = function () { init(); setInterval(function () { runTime(); }, 500); } function init() { clock = document.getElementById('clock'); for (var i = 0; i < textSet.length; i++) { for (var j = 0; j < textSet[i][0].length; j++) { var temp = createLabel(textSet[i][0][j]); clock.appendChild(temp); textSet[i][1].push(temp); } } console.log(textSet) clock.style.transform = "rotate(90deg)"; } function createLabel(text) { var div = document.createElement('div'); div.classList.add('label'); div.innerText = text; return div; } function runTime() { var now = new Date(); var month = now.getMonth(); var day = now.getDate(); var week = now.getDay(); var hour = now.getHours(); var minute = now.getMinutes(); var seconds = now.getSeconds(); var nowValue = [month, day - 1, week, hour, minute, seconds]; initStyle(); //當(dāng)前年月日時(shí)高亮 for (var i = 0; i < nowValue.length; i++) { var num = nowValue[i]; textSet[i][1][num].style.color = '#fff'; } var widthMid = document.body.clientWidth / 2; var heightMid = document.body.clientHeight / 2; for (var i = 0; i < textSet.length; i++) { for (var j = 0; j < textSet[i][0].length; j++) { var r = (i + 1) * 35 + 50 * i; var deg = 360 / textSet[i][1].length * (j - nowValue[i]); var x = r * Math.sin(deg * Math.PI / 180) + widthMid; var y = heightMid - r * Math.cos(deg * Math.PI / 180); var temp = textSet[i][1][j]; temp.style.transform = 'rotate(' + (-90 + deg) + 'deg)'; temp.style.left = x + 'px'; temp.style.top = y + 'px'; } } } function initStyle() { var label = document.getElementsByClassName('label'); for (var i = 0; i < label.length; i++) { label[i].style.color = '#4d4d4d'; } } </script> <title> </title> </head> <body> <div id="clock"></div> </body> </html>
總結(jié)
通過(guò)上面一頓操作,短短幾行代碼實(shí)現(xiàn)了這個(gè)炫酷的方法,在涉及定位每個(gè)節(jié)點(diǎn)位置的時(shí)候,不得不再去復(fù)習(xí)下初中數(shù)學(xué)知識(shí)sin和cos的用法
到此這篇關(guān)于使用JavaScript實(shí)現(xiàn)一個(gè)炫酷的羅盤(pán)時(shí)鐘的文章就介紹到這了,更多相關(guān)JavaScript羅盤(pán)時(shí)鐘內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS+CSS實(shí)現(xiàn)的拖動(dòng)分頁(yè)效果實(shí)例
這篇文章主要介紹了JS+CSS實(shí)現(xiàn)的拖動(dòng)分頁(yè)效果,可實(shí)現(xiàn)鼠標(biāo)拖動(dòng)頁(yè)面翻轉(zhuǎn)到上一頁(yè)或下一頁(yè)的功能,涉及javascript操作頁(yè)面元素與css樣式的相關(guān)技巧,需要的朋友可以參考下2015-05-05js的隱含參數(shù)(arguments,callee,caller)使用方法
本篇文章只要是對(duì)js的隱含參數(shù)(arguments,callee,caller)使用方法進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2014-01-01前端實(shí)現(xiàn)全局主題切換功能實(shí)例代碼
這篇文章主要介紹了如何使用ReactHook和Context實(shí)現(xiàn)全局主題切換的功能,通過(guò)創(chuàng)建一個(gè)Context對(duì)象和一個(gè)ThemeProvider組件,可以將當(dāng)前主題存儲(chǔ)在Context中,并提供一個(gè)切換主題的方法,文中給出了詳細(xì)的代碼示例,需要的朋友可以參考下2025-03-03JavaScript實(shí)現(xiàn)移動(dòng)端橫豎屏檢測(cè)
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)移動(dòng)端橫豎屏檢測(cè),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07javaScript 刪除確認(rèn)實(shí)現(xiàn)方法小結(jié)
因?yàn)閷?duì)于內(nèi)容的刪除是件很重要的事,所以一般的系統(tǒng)中,都需要?jiǎng)h除確認(rèn)一下,以免誤刪,具體的方法如下,大家可以參考下。2009-12-12利用JavaScript實(shí)現(xiàn)靜態(tài)圖片局部流動(dòng)效果
如果你有玩過(guò)《王者榮耀》、《陰陽(yáng)師》?等手游,一定注意到過(guò)它的啟動(dòng)動(dòng)畫(huà)、皮膚立繪卡片等場(chǎng)景,經(jīng)常采用靜態(tài)底圖加局部液態(tài)流動(dòng)效果的簡(jiǎn)單動(dòng)畫(huà),本文將利用JavaScript實(shí)現(xiàn)這一效果,需要的可以參考一下2022-08-08JS寫(xiě)的數(shù)字拼圖小游戲代碼[學(xué)習(xí)參考]
昨天沒(méi)事做,就用JS寫(xiě)了個(gè)數(shù)字拼圖的小游戲,自?shī)首詷?lè)。 可惜關(guān)于逆序數(shù)的問(wèn)題還沒(méi)解決,現(xiàn)在有時(shí)是拼不成的,大家見(jiàn)諒了。2008-10-10JavaScript接口實(shí)現(xiàn)方法實(shí)例分析
這篇文章主要介紹了JavaScript接口實(shí)現(xiàn)方法,結(jié)合實(shí)例形式詳細(xì)分析了JavaScript接口實(shí)現(xiàn)原理、操作步驟與相關(guān)注意事項(xiàng),需要的朋友可以參考下2020-05-05JavaScript加強(qiáng)之自定義callback示例
callback回調(diào)函數(shù)在本文以自定義的方式出現(xiàn),感興趣的朋友可以參考下,希望對(duì)大家有所幫助2013-09-09簡(jiǎn)單的前端js+ajax 購(gòu)物車(chē)框架(入門(mén)篇)
其實(shí),一直想把自己寫(xiě)的一些js給總結(jié)下,也許是能力有限不能把它完美結(jié)合起來(lái)。只能自己默默的看著哪些代碼,無(wú)能為力2011-10-10