This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!

Using native JS, to achieve the compass clock effect

Implementation effect

Implementation approach

  1. Place the numbers in a circle
  2. Get the current time and rotate the ring to the horizontal position by an Angle
  3. Brightens the current time

The idea is simple, but there are a lot of details to consider along the way

The implementation process

Parse a few important parts

  1. Building HTML framework

Because the number is too large, using JS dynamic generation of numbers

<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>
Copy the code
  1. Js generating numbers

This is the function I used to generate date and time numbers, and passing 5 arguments is a bit much

The first argument, num, is the end of the loop passed in

The second parameter date: pass in the tag to be generated where, i.e., who put the tag

The third parameter, target, is passed in the unit, time, minute, second, etc

The fourth argument, bool: passed in whether, specifies whether to fill in zeros

The fifth argument origin: pass in its starting point

Due to the performance cost of using DOM operations, there is a lot of adding of DOM nodes, and if you use a simple for loop to generate nodes, you will have to modify the DOM structure several times

To improve performance, you can create a documentFragment that acts as a temporary container and is added to the parent node one last time

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);
}
Copy the code
  1. Show the dial, which generates the circular effect

All the span boxes were positioned together by positioning, the boxes were opened by transfromX as the radius, and the boxes were evenly scattered by rotating each box at an Angle

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 + ') '; }}Copy the code
  1. Since the page takes time to load, the JS code will not execute immediately and the page will have a blank phase, so add an immediate execute function to render the page as soon as it loads

The implementation code

<! DOCTYPEhtml>
<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;
        }
        /* Position all the spans together */
        .temp span{
            position: absolute;
            left: 50%;
            top: 50%;
            width: 40px;
            height: 20px;
            margin-top: -10px;
            margin-left: -20px;
        }
        span {
            display: block;
        }
        /* The current time changes color */
        .now {
            color: white;
            text-shadow: 0 0 10px white;
        }
        /* Let the year center */
        .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>
        /* Get the element */
        /* Create */ with js because the number is too large
        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 time the penultimate parameter to determine whether to fill in zero */
        create(13,month,'month'.false.1);
        create(31,day,'day'.false.1);
        create(24,hour,'when'.true.0);
        create(60,minute,'points'.true.0);
        create(60,second,'秒'.true.0);
        /* Execute */ immediately
        (timer())
        /* Get the current time */
        setInterval(timer,1000);
        /* In a circle */
        rot(second,'400px');
        rot(minute,'320px');
        rot(hour,'240px');
        rot(day,'160px');
        rot(month,'100px');
        / * * / function
        /* Display the dial function */
        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 + ') '; }}/* Create too many elements, use the document fragmentation method */
        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);
        }
        /* Get time */
        function timer() {
        var time = new Date(a);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();
        /* The year is */
        yearSpan.innerHTML = nowYear + 'years';
        yearSpan.className = 'now';
        Rotate the * / / *
        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' + ') ';
        /* Change the current time style */
        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';
        }
    /* Clear the style function */
        function clearClass(target) {
            for(var i = 0; i < target.children.length; i++ ) { target.children[i].className =' '; }}</script>
</body>
</html>
Copy the code