該時鐘頁面邏輯可以分為幾個關鍵部分:初始化狀態、計算屬性、設置時間、組件掛載和自動更新。下面我會詳細解釋每個部分的具體邏輯和它們在應用中的作用。
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 上,用來動態設置時鐘指針的旋轉角度。
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>