30天JS挑战(第二天)

94 阅读1分钟

第二天挑战(JS时钟)

地址:javascript30.com/

所有内容均上传至gitee,答案不唯一,仅代表本人思路

本人gitee:gitee.com/thats-all-r…

效果

image.png

  • 样式分析

    • 组件整体居中,外部由圆环组成,内部有三个指针
    • 关键样式:border-radio position transform-origin(设置旋转中心)
  • 逻辑分析

    • 进入页面后指针直接指向当前时间
    • 指针根据系统时间进行实时变化

本人代码及思路分析

仅提供布局及逻辑代码

结构:

<div class="main">
  <div class="clock">
    <div class="hour"></div>
    <div class="minute"></div>
    <div class="second"></div>
  </div>
</div>

逻辑:

const hour = document.querySelector('.hour')
const minute = document.querySelector('.minute')
const second = document.querySelector('.second')
let date, h, m, s
const x = () => {
  date = new Date()
  s = date.getSeconds()
  h = date.getHours()
  m = date.getMinutes()
  hour.style.transform = `rotate(${h * 30}deg)`
  minute.style.transform = `rotate(${m * 6 }deg)`
  second.style.transform = `rotate(${s * 6}deg)`
}
setInterval(() => {
  x()
}, 0)

分析:

  • 整体思路: 首先要获取指针对应的元素,其次获取当前的系统时间,根据当前的时间转换成旋转度数作为样式添加到对应的元素中

  • 公式:

    • 小时 / 12 * 360 + 180
    • 分钟 / 60 * 360 + 180
    • 秒 / 60 * 360 + 180
    • 时钟的静态样式写完后,时钟指针会全部指向 6点钟方向,所以需要 +180 来进行度数矫正(具体的矫正方式需要具体分析)
  • 具体实现:

    • 首先通querySelector对类名进行选取
    • 其次创建时/分/秒变量 对系统时间进行获取
    • 根据公式为对应的元素添加transform样式
    • 设置定时器,循环触发函数,做到实时获取的效果
    • 定时器未设置间隔,进入页面后即可直接触发,实现了打开页面同步的效果
  • 弊端分析:

    • 没有给定时器设置间隔,则定时器内的内容会高频次触发,非常影响性能的开销
    • 我这里没有 +180 是因为我在样式上通过 transform将时钟进行了翻转,不建议通过结构上的修改达到这种效果

官方代码

官方代码仅代表该案例原作者思路,不唯一

结构

<div class="clock">
  <div class="clock-face">
    <div class="hand hour-hand"></div>
    <div class="hand min-hand"></div>
    <div class="hand second-hand"></div>
  </div>
</div>

逻辑

const secondHand = document.querySelector('.second-hand');
const minsHand = document.querySelector('.min-hand');
const hourHand = document.querySelector('.hour-hand');
​
function setDate() {
  const now = new Date();
​
  const seconds = now.getSeconds();
  const secondsDegrees = ((seconds / 60) * 360 + 90);
  secondHand.style.transform = `rotate(${secondsDegrees}deg)`;
​
  const mins = now.getMinutes();
  const minsDegrees = ((mins / 60) * 360) + ((seconds/60)*6 + 90);
  minsHand.style.transform = `rotate(${minsDegrees}deg)`;
​
  const hour = now.getHours();
  const hourDegrees = ((hour / 12) * 360) + ((mins/60)*30 + 90);
  hourHand.style.transform = `rotate(${hourDegrees}deg)`;
}
​
setInterval(setDate, 1000);
​
setDate();

分析

仅代表本人对该代码的分析

  • 整体思路: 首先要获取指针对应的元素,其次获取当前的系统时间,根据当前的时间转换成旋转度数作为样式添加到对应的元素中

  • 具体实现:

    • 通过now Date创建日期对象
    • 通过document.querySelector属性名的方式获取元素
    • 通过公式计算获取对应的度数,并赋值给对应元素
    • 先执行一次setDate,后用定时器进行间隔循环执行
  • 优点:

    • 设置了时间间隔,避免高频次的触发,可以提升性能
    • 单独执行一次setDate可以保证当定时器被阻塞的时候,页面依然可以正常的先渲染一遍