JavaScript 30天编码挑战——第 2 天

这是我参与更文挑战的第4天,活动详情查看: 更文挑战

2. Js and CSS Clock

一、效果展示

这里指的是我们补充 JavaScript 代码之前的初始样式和作者完成的最终样式。

index-START.html

image.png

index-FINISHED.html

动画.gif

我的最终效果

动画11.gif

二、实现

最终代码

<script>
    ;(function(){

        const second = document.querySelector('.second-hand');
        const min = document.querySelector('.min-hand');
        const hour = document.querySelector('.hour-hand');
        
        function setClock(){
            let data = new Date()

            let secondDeg = data.getSeconds()*6 //(360/60)
            let minDeg = data.getMinutes()*6 + data.getSeconds() *6 /60   //(360/60)
            let hourDeg = data.getHours()*30 + data.getHours() * 30 / 60  //(360/12)

            second.style.transform = `rotate(${secondDeg}deg)`
            min.style.transform = `rotate(${minDeg}deg)`
            hour.style.transform = `rotate(${hourDeg}deg)`

        }
        
        // function timeoutHandler(){
        //   setClock()
        //   setTimeout(timeoutHandler,1000)
        // }

        // function animationHandler(){
        //   setClock()
        //   window.requestAnimationFrame(animationHandler);
        // }

        setClock()  //初始化画面

        // 计时器 setInterval  setTimeout   requestAnimationFrame

        setInterval(setClock,1000)   //设置一次  执行多次 

        // setTimeout(timeoutHandler,1000)  //设置间隔  持续执行

        // window.requestAnimationFrame(animationHandler);   //处理画面更新的 setTimeout
    })()

  </script>
复制代码

大家可能注意到了这里的立即执行合数和昨天的相比对了一个分号。加这个分号的意义就是,如果你的整个 script 标签里只有一个立即执行函数,那么不加分号也是没有关系的;如果你的代码里边有不同的层次,比如有防抖的工具,其他封装的工具,如果你的前面没有分号的话,这样所有的方法就会连在一起,这样就可能会出错。这里写了主要起一个预防的作用。

三、总结回顾

从上面的代码中可以看出,其实我们这个功能主要做了这么几件事:

实现表盘指针样式
实现旋转效果
一秒改变一次指针的状态位置
获取实时时间

过程分解

1.首先添加了一个表盘圆心样式;

/* 表盘圆心 */
    .clock-face::after{
      content: "";
      display: block;
      width: 30px;
      height: 30px;
      border-radius: 50%;
      position:absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%,-50%);
      background-color: #EFEFEF;
    }
复制代码

2.实现时分秒针的展示和初始位置

/* .hand {
      width: 50%;
      height: 6px;
      background: black;
      position: absolute;
      top: 50%;
    } */
    
    /* 这里改变了一个作者的样式 */
    .hand {
      position: absolute;
      width: 100%;
      height: 100%;
    }

    /* 秒针 */
    .second-hand::after{
      content: "";
      position: absolute;
      display: block;
      width: 10px;
      height: 50%;
      background-color: #FF0000;
      left:50%;
      bottom: 50%;
      transform: translate(-50%,0%);
    }

    /* 分针 */
    .min-hand::after{
      content: "";
      position: absolute;
      display: block;
      width: 12px;
      height: 40%;
      background-color: #EFEFEF;
      left:50%;
      bottom: 50%;
      transform: translate(-50%,0%);
    }

    /* 时针 */
    .hour-hand::after{
      content: "";
      position: absolute;
      display: block;
      width: 15px;
      height: 30%;
      background-color: #EFEFEF;
      left:50%;
      bottom: 50%;
      transform: translate(-50%,0%);
    }
复制代码

这里稍微提及一下,改了作者的样式,跟作者的有什么区别:

(1)这是原作者的效果,他的针的旋转效果就是单纯的一个指针在旋转

image.png

(2)这是改变之后的样式,旋转是以一个正方形做旋转的,这样的话定位会比较容易点,定位是定在正方形内部的。

image.png

3.JavaScript 事件处理

(1)获取三个指针对应元素

        const second = document.querySelector('.second-hand');
        const min = document.querySelector('.min-hand');
        const hour = document.querySelector('.hour-hand');
复制代码

(2)创建 setClock 方法

   ① 创建 Date 对象

   ② 获取时分秒没个指针对应的角度

        function setClock(){
            let data = new Date()

            let secondDeg = data.getSeconds()*6 //(360/60)
            let minDeg = data.getMinutes()*6 + data.getSeconds() *6 /60   //(360/60)
            let hourDeg = data.getHours()*30 + data.getHours() * 30 / 60  //(360/12)

            second.style.transform = `rotate(${secondDeg}deg)`
            min.style.transform = `rotate(${minDeg}deg)`
            hour.style.transform = `rotate(${hourDeg}deg)`

        }
复制代码
  1. 利用定时器自动更新时间
setInterval(setClock,1000)   //设置一次  执行多次 
复制代码

四、重难点

计算每个指针对应的角度

1.一开始我是这样写的,但是这样写的话,出来的效果就会使这样的,大家注意分针的转动效果。

动画111.gif
这里的分针在秒钟执行完一圈之后,是在开始下一圈转动的时候,秒针角度增加了一分钟的角度,这样虽然实现了效果,但是无论是在视觉上,还是在实现的最终结果上,都是不太对的。

            let secondDeg = data.getSeconds()*6 //(360/60)
            let minDeg = data.getMinutes()*6   //(360/60)
            let hourDeg = data.getHours()*30  //(360/12)
复制代码

2.严格意义上来说,分针的移动效果应该是现在这样的,注意鼠标光标下面分针的移动。

动画1112.gif
不知道大家有没有注意到,这里的分针是在秒针转动的过程中,按照转动的角度平均了这一分钟的移动,这样的移动效果才是比较正常的视觉效果。

在 Wes Bos 给出的解决方案中,时针是每一小时跳动一次,要想模拟真实的时钟,要使时针在一小时内缓慢的移动到下一个时间点。所以可以利用上分钟,计算每一分钟对时针的角度影响,将加到时针角度上即可。

//作者的方案
const hourDeg = (90 + (hour / 12) * 360 + (min / 12 / 60) * 360);
复制代码


            let secondDeg = data.getSeconds()*6 //(360/60)
            let minDeg = data.getMinutes()*6 + data.getSeconds() *6 /60   //(360/60)
            let hourDeg = data.getHours()*30 + data.getHours() * 30 / 60  //(360/12)
复制代码

定时器

在我的最终代码里,三种定时器的使用我都使用了,最终我是用的是 setInterval,定时器 setInterval 可以每隔一段固定时间将执行操作放入执行队列,我们利用它这个特性,让其在插入页面后每一秒钟更新一次时间,实现秒针转动的效果。

1. setInterval

MDN 文档使用方法:developer.mozilla.org/zh-CN/docs/…

 setInterval(setClock,1000)   //设置一次  执行多次 
复制代码

2. setTimeout

MDN 文档使用地址:developer.mozilla.org/zh-CN/docs/…

这里只是展示实现效果

      function timeoutHandler(){
        setClock()
        setTimeout(timeoutHandler,1000)
      }
      
      setTimeout(timeoutHandler,1000)  //设置间隔  持续执行
复制代码

3. requestAnimationFrame

window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行

这里只是展示一下用法,具体的用法请查看 MDN 文档:developer.mozilla.org/zh-CN/docs/…

      function animationHandler(){
        setClock()
        window.requestAnimationFrame(animationHandler);
      }
      
      window.requestAnimationFrame(animationHandler);   //处理画面更新的 setTimeout
复制代码

今天的分享到此结束了,记得持续学习!

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享