动态钟表

实现一个动态改变的钟表

效果如下

<!DOCTYPE html>
<html lang="zh-cn">
  <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>
      body {
        margin: 0;
      }

      .column {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
      }

      .container {
        height: 100vh;
      }

      .clock {
        position: relative;
        width: 40vw;
        height: 40vw;
        border-radius: 50%;
        border: 0.6vw solid rgb(134, 134, 134);
        background-color: antiquewhite;
        overflow: hidden;
        box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.144);
      }

      .time {
        position: absolute;
        top: 20%;
        font-size: 3.5vw;
        font-weight: bold;
        color: rgb(102, 102, 102);
        padding: 0.3vw;
        border-radius: 0.7vw;
        box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.349);
      }

      .plant {
        position: relative;
        width: 100%;
        height: 100%;
        border-radius: 50%;
        filter: drop-shadow(0.5vw 0.4vw 0.4vw rgba(0, 0, 0, 0.2));
      }

      .plant::after {
        content: "";
        position: absolute;
        top: calc(50% - 1.35vw);
        left: calc(50% - 1.35vw);
        width: 2vw;
        height: 2vw;
        border-radius: 50%;
        border: 0.35vw solid rgb(129, 129, 129);
        background-color: rgb(236, 236, 236);
      }

      .hour,
      .minute,
      .second {
        position: absolute;
        left: 50%;
        top: 50%;
        width: 9vw;
        height: 0.6vw;
        background-color: rgb(70, 70, 70);
        transform: rotate(-90deg);
        transform-origin: 0% 50%;
        transition: transform 400ms ease-in-out;
      }

      .minute {
        width: 15vw;
        height: 0.4vw;
      }

      .second {
        width: 17vw;
        height: 0.3vw;
      }
    </style>
  </head>
  <body>
    <div class="container column">
      <div class="clock column" onclick="toggleClock()">
        <div class="time"></div>
        <div class="plant">
          <div class="hour"></div>
          <div class="minute"></div>
          <div class="second"></div>
        </div>
      </div>
    </div>

    <script>
      window.requestAnimationFrame = (function () {
        return (
          window.requestAnimationFrame ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame ||
          function (callback) {
            return window.setTimeout(callback, 1000 / 60);
          }
        );
      })();

      window.cancelAnimationFrame = (function () {
        return (
          window.cancelAnimationFrame ||
          window.webkitCancelAnimationFrame ||
          window.mozCancelAnimationFrame ||
          window.msCancelAnimationFrame ||
          function (id) {
            window.clearTimeout(id);
          }
        );
      })();

      window.onload = function () {
        startClock();
      };

      const toggleClock = (function() {
        let state = true;
        return function() {
          if (state) stopClock();
          else startClock();
          state = !state;
        };
      })();

      function startClock() {
        const timeElem = document.querySelector('.time');
        const clockElem = document.querySelector('.clock');
        const fn = function() {
          updateClock(timeElem, clockElem);
          window.clockAnimationId = window.requestAnimationFrame(fn);
        };
        window.clockAnimationId = window.requestAnimationFrame(fn);
      }

      function stopClock() {
        window.cancelAnimationFrame(window.clockAnimationId);
      }

      function updateClock(timeElem, clockElem) {
        const curTime = _getTime();
        _setTime(timeElem, curTime);
        _setClock(clockElem, curTime);
      }
      
      function _getTime() {
        const date = new Date();
        return date;
      }

      function _setTime(elem, time) {
        elem.textContent = time
          .toLocaleString("chinese", { hour12: false })
          .substr(-8, 8);
      }

      function _setClock(elem, time) {
        let hour = time.getHours();
        hour = hour >= 12 ? hour - 12 : hour;
        const minute = time.getMinutes();
        const second = time.getSeconds();
        const hourPer = hour / 12;
        const minutePer = minute / 60;
        const secondPer = second / 60;
        const hourRotate = 360 * hourPer + minutePer * 30 + secondPer * 0.5 - 90;
        const minuteRotate = 360 * minutePer + secondPer * 6 - 90;
        const secondRotate = 360 * secondPer - 90;

        const hourElem = elem.querySelector(".hour");
        const minuteElem = elem.querySelector(".minute");
        const secondElem = elem.querySelector(".second");
        hourElem.style.transform = `rotate(${hourRotate}deg)`;
        minuteElem.style.transform = `rotate(${minuteRotate}deg)`;
        secondElem.style.transform = `rotate(${secondRotate}deg)`;
      }
    </script>
  </body>
</html>

版权

本作品采用 CC BY-NC-ND 4.0 授权。