iT邦幫忙

2024 iThome 鐵人賽

DAY 2
0

說明

該時鐘頁面邏輯可以分為幾個關鍵部分:初始化狀態、計算屬性、設置時間、組件掛載和自動更新。下面我會詳細解釋每個部分的具體邏輯和它們在應用中的作用。

  1. Setup 是 Vue 3 的 Composition API 函數,負責初始化組件的狀態和邏輯。ref 是用來定義響應式變量的,這裡定義了三個 ref 變量,分別用來存儲時針、分針和秒針的旋轉角度
  • hourDegrees:存儲時針的旋轉角度。
  • minuteDegrees:存儲分針的旋轉角度。
  • secondDegrees:存儲秒針的旋轉角度。
  1. 計算屬性
const hourStyle = computed(() => ({
    transform: `rotate(${hourDegrees.value}deg)`,
}));

const minuteStyle = computed(() => ({
    transform: `rotate(${minuteDegrees.value}deg)`,
}));

const secondStyle = computed(() => ({
    transform: `rotate(${secondDegrees.value}deg)`,
}));

computed 是 Vue 3 的 Composition API 函數,用於創建計算屬性。這些屬性是基於其他響應式數據計算得出的,並且會在依賴的數據發生變化時自動更新。

•	hourStyle:根據 hourDegrees 的值計算並返回時針的旋轉樣式。
•	minuteStyle:根據 minuteDegrees 的值計算並返回分針的旋轉樣式。
•	secondStyle:根據 secondDegrees 的值計算並返回秒針的旋轉樣式。

這些計算屬性將被綁定到模板中的相應 div 上,用來動態設置時鐘指針的旋轉角度。

  1. 設置時間
const setDate = () => {
    const now = new Date();
    const seconds = now.getSeconds();
    const secondsValue = (seconds / 60) * 360 + 90;

    const mins = now.getMinutes();
    const minsValue = (mins / 60) * 360 + (seconds / 60) * 6 + 90;

    const hour = now.getHours();
    const hourValue = (hour / 12) * 360 + (mins / 60) * 30 + 90;

    secondDegrees.value = secondsValue;
    minuteDegrees.value = minsValue;
    hourDegrees.value = hourValue;
};
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Vue + CSS Clock</title>
        <style>
            html {
              background: linear-gradient(to bottom, #018ded, #ffffff);
                background-size: cover;
                font-family: "helvetica neue";
                text-align: center;
                font-size: 10px;
            }

            body {
                margin: 0;
                font-size: 2rem;
                display: flex;
                flex: 1;
                min-height: 100vh;
                align-items: center;
            }

            .clock {
                width: 30rem;
                height: 30rem;
                border: 20px solid white;
                border-radius: 50%;
                margin: 50px auto;
                position: relative;
                padding: 2rem;
                box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.1), inset 0 0 0 3px #efefef, inset 0 0 10px black,
                    0 0 10px rgba(0, 0, 0, 0.2);
            }

            .clock-face {
                position: relative;
                width: 100%;
                height: 100%;
                transform: translateY(-3px);
                /* account for the height of the clock hands */
            }

            .hand {
                width: 50%;
                height: 6px;
                background: black;
                position: absolute;
                top: 50%;
                transform-origin: 100%;
                transform: rotate(90deg);
                transition: all 0.05s;
                transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);
            }
        </style>
        <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    </head>

    <body id="app">
        <div class="clock">
            <div class="clock-face">
                <div class="hand" :style="hourStyle"></div>
                <div class="hand" :style="minuteStyle"></div>
                <div class="hand" :style="secondStyle"></div>
            </div>
        </div>
    </body>
    <script>
        const { createApp, ref, onMounted, computed } = Vue;

        createApp({
            setup() {
                const hourDegrees = ref(0);
                const minuteDegrees = ref(0);
                const secondDegrees = ref(0);

                const hourStyle = computed(() => ({
                    transform: `rotate(${hourDegrees.value}deg)`,
                }));

                const minuteStyle = computed(() => ({
                    transform: `rotate(${minuteDegrees.value}deg)`,
                }));

                const secondStyle = computed(() => ({
                    transform: `rotate(${secondDegrees.value}deg)`,
                }));

                const setDate = () => {
                    const now = new Date();
                    const seconds = now.getSeconds();
                    const secondsValue = (seconds / 60) * 360 + 90;

                    const mins = now.getMinutes();
                    const minsValue = (mins / 60) * 360 + (seconds / 60) * 6 + 90;

                    const hour = now.getHours();
                    const hourValue = (hour / 12) * 360 + (mins / 60) * 30 + 90;
                    secondDegrees.value = secondsValue;
                    minuteDegrees.value = minsValue;
                    hourDegrees.value = hourValue;
                };

                onMounted(() => {
                    setDate();
                    setInterval(setDate, 1000);
                });

                return {
                    hourStyle,
                    minuteStyle,
                    secondStyle,
                };
            },
        }).mount("#app");
    </script>
</html>

連結

  1. Demo
  2. Github

上一篇
01 - Vue Drum Kit
下一篇
03 - CSS Variables
系列文
使用 Vue 3 做出 30 個 Side Project7
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言