你是否曾經想過,讓時間不只是冷冰冰的數字,而是變成一個動態、直觀、充滿視覺衝擊的體驗?
今天,我們要用 Vue.js 帶你進入計時器與圈圈進度條的世界!
不再只是普通的倒數,而是結合進度條和圈圈的互動效果,讓計時變得更酷、更吸引眼球。
無論你是用來做任務倒數、跑步計時,還是追蹤項目進展,這個動態計時器搭配圈圈進度條的效果,保證讓你的頁面煥然一新,增強使用者的體驗感。
準備好來學習這個超實用的效果嗎?
那就跟我一起進入今天的實戰吧!
這個超酷的計時器還搭配了圈圈進度條,讓倒數時間變得更直觀又炫酷!
再加上「Start」、「Pause」、「Reset」三個按鈕,每個按鈕還有簡單的 hover 回饋,互動性滿分~
用 Vue.js 輕鬆打造這個小功能變得有趣又動感~
透過精美的動效,讓整體體驗更生動,還能瞬間抓住使用者的目光!
計時器的基礎設置:
ref
和 computed
來管理時間變量和格式化顯示。進度條設計:
stroke-dasharray
和 stroke-dashoffset
,讓進度條隨著時間的流逝動態改變。<template>
<div class="flex justify-center items-center h-screen bg-[#5628EE] font-mono">
<div class="container">
<div class="flex justify-center items-center relative">
<svg class="h-[150px] w-[150px]" viewBox="0 0 100 100">
<defs>
<linearGradient id="warm-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#85FFBD"></stop>
<stop offset="100%" style="stop-color:#FFFB7D"></stop>
</linearGradient>
</defs>
<!-- Circle with animation -->
<circle class="fill-none transition-all duration-1000 ease-linear" cx="50" cy="50" r="45"
stroke-width="4" style="stroke: url(#warm-gradient); stroke-dasharray: 282.743;"
:stroke-dashoffset="dashOffset" />
</svg>
<div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-4xl text-white">
{{ formattedTime }}
</div>
</div>
<div class="mt-5 flex flex-col items-center">
<input v-model.number="timeInput" placeholder="請輸入秒數" min="1"
class="outline-none border-none w-70 h-10 border-white text-[#5628EE] text-center rounded-full">
<div class="mt-4 flex space-x-6">
<button @click="startTimer" class="inline-flex items-center px-4 py-2 bg-red-600 hover:bg-red-700 text-white text-sm font-medium rounded-md">
Start
</button>
<button @click="pauseTimer" class="bg-gray-300 p-4 text-center text-[#5628EE] flex flex-wrap justify-center rounded-md hover:bg-gray-400">
Pause
</button>
<button @click="resetTimer" class="inline-flex items-center px-4 py-2 bg-green-700 text-white hover:bg-green-800 text-sm font-medium rounded-md">
Reset
</button>
</div>
</div>
</div>
</div>
</template>
stroke-dasharray
和 stroke-dashoffset
的 SVG 圓形來呈現進度條。當倒數開始時,進度條會根據剩餘時間不斷減少。linearGradient
)來強化視覺效果,使進度條看起來更加立體且炫彩。<script lang="ts" setup>
import { ref, computed } from 'vue';
const timeInput = ref<number>(0);
const remainingTime = ref<number>(0);
const totalTime = ref<number>(0);
const isPaused = ref<boolean>(false);
const dashOffset = ref<string>('282.743');
let timer: ReturnType<typeof setInterval> | null = null;
// 格式化時間,顯示為 MM:SS
const formattedTime = computed(() => {
const mins = Math.floor(remainingTime.value / 60);
const secs = remainingTime.value % 60;
return `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
});
// 更新計時器與圈圈的 stroke-dashoffset
const updateTimer = () => {
if (remainingTime.value <= 0) {
clearInterval(timer!);
dashOffset.value = '0';
return;
}
remainingTime.value--;
dashOffset.value = (282.743 * (remainingTime.value / totalTime.value)).toFixed(3);
};
// 開始計時
const startTimer = () => {
if (isPaused.value && timer) {
isPaused.value = false;
timer = setInterval(updateTimer, 1000);
return;
}
clearInterval(timer!);
totalTime.value = timeInput.value || 0;
remainingTime.value = totalTime.value;
if (totalTime.value > 0) {
dashOffset.value = '282.743';
timer = setInterval(updateTimer, 1000);
}
};
// 暫停計時
const pauseTimer = () => {
if (!isPaused.value) {
clearInterval(timer!);
isPaused.value = true;
}
};
// 重置計時器
const resetTimer = () => {
clearInterval(timer!);
remainingTime.value = 0;
dashOffset.value = '282.743';
isPaused.value = false;
};
</script>
startTimer
函式會根據使用者輸入的秒數啟動計時,並每秒更新一次倒數時間。同時,進度條也會根據剩餘時間動態減少。pauseTimer
允許使用者暫停計時,而 resetTimer
則會重置計時器和進度條,讓使用者可以重新開始倒數。這個功能的主要目的是在使用者點擊「開始」按鈕時,根據輸入的時間來啟動倒數計時,同時啟動進度條的動畫。
const startTimer = () => {
// 如果計時器是暫停狀態且已經有一個計時器在運行,就恢復計時
if (isPaused.value && timer) {
isPaused.value = false;
timer = setInterval(updateTimer, 1000); // 每秒更新計時器
return;
}
// 清除當前的計時器,準備重新開始
clearInterval(timer!);
// 初始化計時時間與總時間
totalTime.value = timeInput.value || 0; // 使用者輸入的時間(秒)
remainingTime.value = totalTime.value; // 剩餘的倒數時間初始化為總時間
// 如果輸入時間大於 0,啟動計時器
if (totalTime.value > 0) {
dashOffset.value = '282.743'; // 設定圓圈進度條的初始值
timer = setInterval(updateTimer, 1000); // 每秒更新一次計時器
}
};
clearInterval
),然後根據使用者輸入的時間重新啟動。totalTime
和 remainingTime
來初始化總時間和剩餘時間,並設置進度條的初始位置。setInterval
每秒執行一次 updateTimer
,讓計時器和進度條同步更新。這個功能的目的是在使用者點擊「暫停」按鈕時暫停計時器,但保留當前的剩餘時間和進度條位置,以便稍後可以繼續倒數。
const pauseTimer = () => {
if (!isPaused.value) { // 如果計時器不是暫停狀態
clearInterval(timer!); // 暫停計時器
isPaused.value = true; // 標記為暫停狀態
}
};
clearInterval
來暫停計時器的倒數。isPaused
設定為 true
,以標記計時器當前處於暫停狀態。這個功能的目的是在使用者點擊「重置」按鈕時,將計時器和進度條重置為初始狀態。
const resetTimer = () => {
clearInterval(timer!); // 停止當前的計時器
remainingTime.value = 0; // 將剩餘時間重置為 0
dashOffset.value = '282.743'; // 重置進度條的位置
isPaused.value = false; // 標記為非暫停狀態
};
remainingTime
重置為 0,表示計時已經結束。dashOffset
也會被重置為初始狀態(即進度條的滿格值),以準備下一次的倒數計時。isPaused
設定為 false
,這樣在下一次點擊「開始」時,計時器將重新運行。這個函數負責在每次倒數時更新剩餘時間和進度條的位置。
const updateTimer = () => {
// 如果剩餘時間小於等於 0,清除計時器並將進度條歸 0
if (remainingTime.value <= 0) {
clearInterval(timer!);
dashOffset.value = '0';
return;
}
// 更新剩餘時間與進度條位置
remainingTime.value--;
dashOffset.value = (282.743 * (remainingTime.value / totalTime.value)).toFixed(3);
};
updateTimer
函數每秒更新一次,當剩餘時間減少時,進度條也會相應地縮減。remainingTime.value <= 0
),計時器會停止,進度條完全消失。dashOffset
的計算是根據剩餘時間和總時間之間的比例來更新進度條的長度。視覺化計時器:
stroke-dasharray
與 stroke-dashoffset
,我們可以輕鬆地將時間的變化轉化為可視化的進度條。計時器的可互動性:
倒數不是結束,而是下一個開始的倒計時! ⏳
每個倒數的瞬間,其實都是為了下一次的突破做準備。
無論進度條怎麼走,重要的是你怎麼利用這些時間去成就更大的夢想。
計時器告訴我們,時間是有限的,但機會卻是無限的!每一次的「Reset」都是讓我們更強大的起點,下一個挑戰永遠在等著你。✨
所以,勇敢按下「Start」,無論過程如何,記住,你的每一步都是進步的見證!
現在,就讓這些技術成為你實現夢想的利器,邁向下一個精彩吧!🚀