抖音超火的罗盘时钟

抖音超火的罗盘时钟

利用原生js,实现的罗盘时钟效果

实现效果

罗盘

实现思路

  1. 将数字摆成圆环
  2. 获取当前时间,让圆环旋转一定的角度,转到水平位置
  3. 将当前时间变亮

实现的思路还是很简单的,但是在过程中会有很多的细节需要考虑到

实现过程

解析几个重要部分

  1. 搭建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>
  1. 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);
}
  1. 展示表盘,也就是生成圆形的效果

通过定位将全部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 + ')' ;
            }
        }
  1. 由于页面加载需要一定时间,会导致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>
(完)