抖音超火的罗盘时钟
利用原生js,实现的罗盘时钟效果
实现效果
实现思路
- 将数字摆成圆环
- 获取当前时间,让圆环旋转一定的角度,转到水平位置
- 将当前时间变亮
实现的思路还是很简单的,但是在过程中会有很多的细节需要考虑到
实现过程
解析几个重要部分
- 搭建HTML框架
因为数字的量太大,采用js动态生成数字
<div class="clock">
<div class=" temp year">
<span></span>
</div>
<div class="temp month"></div>
<div class="temp day"></div>
<div class="temp hour"></div>
<div class="temp minute"></div>
<div class="temp second"></div>
</div>
- js生成数字
这个函数是我用来生成日期,时间数字的,传入了5个参数确实有点多了
第一个参数num
:传入循环的终点
第二个参数date
:传入要生成的标签加在哪里,也就是是谁下的标签
第三个参数target
:传入单位,时分秒这些
第四个参数bool
:传入是否,用来指定是否要补零
第五个参数origin
:传入它的起始点
由于使用 dom 操作会消耗性能,这里需要大量的添加 dom 节点,如果使用简单的for循环生成节点,会多次的修改 dom 结构
为了提高性能,可以建立一个文档碎片
documentfragment
,作为临时容器,最后一次再加到父节点中
function create(num,date,target,bool,origin) {
var fragment = document.createDocumentFragment();
for(var i = origin; i < num ; i ++) {
var j = i;
if(bool){
j = j > 9 ? j : '0' + j;
}
var span = document.createElement('span');
span.appendChild(document.createTextNode(j + target));
fragment.appendChild(span);
}
date.appendChild(fragment);
}
- 展示表盘,也就是生成圆形的效果
通过定位将全部span盒子定位在一起,通过transfromX
将盒子一开,作为半径,再通过给每个盒子旋转一份角度,使得盒子均匀的散开
function rot(target,distance) {
var rotBox = target.children;
for(var i = 0 ;i < rotBox.length ; i ++ ){
rotBox[i].style.transform = 'rotate(' + (360 / rotBox.length ) * i + 'deg)' + 'translateX(' + distance + ')' ;
}
}
- 由于页面加载需要一定时间,会导致js代码未能立即执行,页面会有一段空白阶段,所以添加一个立即执行函数让页面一加载就有效果呈现
实现代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
background-color: rgb(8, 8, 8);
color: rgb(92, 91, 91);
font-size: 18px;
}
.clock {
position: absolute;
left:50%;
top:50%;
width: 1000px;
height: 1000px;
transform: translate(-50%,-50%);
}
.temp {
position: absolute;
top: 0;
width: 1000px;
height: 1000px;
transition: all .5s;
}
/* 把所有的span定位到一起 */
.temp span{
position: absolute;
left: 50%;
top: 50%;
width: 40px;
height: 20px;
margin-top: -10px;
margin-left: -20px;
}
span {
display: block;
}
/* 现在的时间变色 */
.now {
color: white;
text-shadow: 0 0 10px white;
}
/* 让年份居中显示 */
.year span {
font-size: 24px;
width: 90px;
margin-left: -35px;
margin-top: -15px;
}
</style>
</head>
<body>
<div class="clock">
<div class=" temp year">
<span></span>
</div>
<div class="temp month"></div>
<div class="temp day"></div>
<div class="temp hour"></div>
<div class="temp minute"></div>
<div class="temp second"></div>
</div>
<script>
/* 获取元素 */
/* 因为数量太大所以通过js来创建 */
var year = document.querySelector('.year');
var month = document.querySelector('.month');
var day = document.querySelector('.day');
var hour = document.querySelector('.hour');
var minute = document.querySelector('.minute');
var second = document.querySelector('.second');
var yearSpan = year.querySelector('span');
/* 创建时间 倒数第二个参数判断要不要补零*/
create(13,month,'月',false,1);
create(31,day,'日',false,1);
create(24,hour,'时',true,0);
create(60,minute,'分',true,0);
create(60,second,'秒',true,0);
/* 立即执行一次 */
(timer())
/* 获取当前时间 */
setInterval(timer,1000);
/* 摆成圆形 */
rot(second,'400px');
rot(minute,'320px');
rot(hour,'240px');
rot(day,'160px');
rot(month,'100px');
/* 函数 */
/* 展示表盘函数 */
function rot(target,distance) {
var rotBox = target.children;
for(var i = 0 ;i < rotBox.length ; i ++ ){
rotBox[i].style.transform = 'rotate(' + (360 / rotBox.length ) * i + 'deg)' + 'translateX(' + distance + ')' ;
}
}
/* 创建的元素过多,采用建立文档碎片的方式 */
function create(num,date,target,bool,origin) {
var fragment = document.createDocumentFragment();
for(var i = origin; i < num ; i ++) {
var j = i;
if(bool){
j = j > 9 ? j : '0' + j;
}
var span = document.createElement('span');
span.appendChild(document.createTextNode(j + target));
fragment.appendChild(span);
}
date.appendChild(fragment);
}
/* 获取时间 */
function timer() {
var time = new Date();
var nowYear = time.getFullYear();
var nowMonth = time.getMonth() + 1;
var nowDay = time.getDate();
var nowHour = time.getHours();
var nowMinute = time.getMinutes();
var nowSecond = time.getSeconds();
/* 年份直接填 */
yearSpan.innerHTML = nowYear + '年';
yearSpan.className = 'now';
/* 旋转 */
var rotateH = nowHour * 15 ;
var rotateM = nowMinute * 6;
var rotateS = nowSecond * 6;
var rotateD = (nowDay - 1) * 12;
var rotateMo = (nowMonth - 1 ) * 30;
second.style.transform = 'rotate(' + (- rotateS) + 'deg' + ')';
minute.style.transform = 'rotate(' + (- rotateM) + 'deg' + ')';
hour.style.transform = 'rotate(' + (- rotateH) + 'deg' + ')';
day.style.transform = 'rotate(' + (- rotateD) + 'deg' + ')';
month.style.transform = 'rotate(' + (- rotateMo) + 'deg' + ')';
/* 更改当前时间的样式 */
clearClass(month)
clearClass(day);
clearClass(hour);
clearClass(minute);
clearClass(second);
month.children[nowMonth - 1].className = 'now';
day.children[nowDay - 1].className = 'now';
hour.children[nowHour].className = 'now';
minute.children[nowMinute].className = 'now';
second.children[nowSecond].className = 'now';
}
/* 清除样式的函数 */
function clearClass(target) {
for(var i = 0;i < target.children.length; i++ ) {
target.children[i].className = '';
}
}
</script>
</body>
</html>