Circle 環形進度條 - Vant 4
Circle 環形進度條
⭕ 介紹
Circle 環形進度條就像一個優雅的時鐘錶盤,以圓潤流暢的弧線訴說著進度的故事 🕐。它不僅僅是一個簡單的進度指示器,更像是一位貼心的嚮導,用絲滑的動畫和漸變的色彩,將枯燥的數字轉化為賞心悅目的視覺盛宴。無論是展示檔案下載進度、任務完成度,還是技能熟練度,Circle 都能以其獨特的圓環魅力,讓使用者在等待中也能感受到美的享受 ✨。
📦 引入
透過以下方式來全域註冊元件,更多註冊方式請參考元件註冊。
import { createApp } from'vue'; import { Circle } from'vant'; const app = createApp(); app.use(Circle);🎯 程式碼演示
基礎用法
Circle 的魅力在於它的智慧動畫系統 🎬!rate 屬性就像是給進度條設定的目標,而 v-model:current-rate 則是即時追蹤動畫進展的小助手。當你改變 rate 值時,Circle 會像一位優雅的舞者,以 speed 設定的節拍,從當前位置緩緩舞向目標位置,每一幀都充滿了流暢的美感,讓等待變成一種享受!
import { ref, computed } from'vue';
export default {
setup() {
const currentRate = ref(0);
const text = computed(
() => currentRate.value.toFixed(0) + '%');
return { text, currentRate, };
},
};寬度定制
想要讓你的進度條更有個性?stroke-width 屬性就是你的魔法畫筆 🎨!它控制著圓環的粗細程度,就像調節畫筆的筆觸一樣。無論你喜歡纖細優雅的線條,還是粗獷有力的筆觸,都能透過這個屬性輕鬆實現。預設值 40 已經很完美,但你完全可以根據設計需求自由調節!
stroke-width 的單位不是 px,如果你想知道 stroke-width 與 px 的換算關係,可以透過如下公式計算:
// SVG 的 viewBox 大小
const viewBox = 1000 + strokeWidth;
// Circle 元件的寬度,預設為 100px
const circleWidth = 100;
// 最終渲染出來的進度條寬度(px)
const pxWidth = (strokeWidth * circleWidth) / viewBox;顏色定制
色彩是 Circle 的靈魂所在 🌈!透過 color 屬性,你可以為進度條披上任何你喜歡的顏色外衣,而 layer-color 屬性則負責裝扮底層的軌道。就像為舞台設置燈光一樣,合適的顏色搭配能讓你的進度條在介面中脫穎而出,成為最亮眼的那顆星!
漸變色
想要更加炫酷的視覺效果?color 屬性還支援漸變色魔法 ✨!只需傳入一個物件,就能創造出從一種顏色平滑過渡到另一種顏色的絢麗效果,讓你的進度條如彩虹般絢爛多彩!
import { ref } from'vue';
export default {
setup() {
const currentRate = ref(0);
const gradientColor = {
'0%': '#3fecff',
'100%': '#6149f6',
};
return { currentRate, gradientColor, };
},
};逆時針方向
有時候,反向的美也別有一番風味 🔄!將 clockwise 設定為 false,Circle 就會像時光倒流一樣,以逆時針的方向優雅地展示進度。這種獨特的動畫方向能為你的應用增添一絲神秘感和創意感!
大小定制
大小由你掌控!透過 size 屬性,你可以隨心所欲地調整 Circle 的尺寸 📏。無論是精緻小巧的迷你版,還是醒目大氣的巨無霸版,都能完美適配你的介面設計需求!
起始位置
誰說進度條一定要從頂部開始?Circle 給你更多選擇的自由 🧭!透過 start-position 屬性,你可以讓進度從頂部、左側、右側或底部任意位置開始,就像指南針一樣,指向你想要的任何方向!
API
Props
| 參數 | 說明 | 類型 | 預設值 |
|---|---|---|---|
| v-model:current-rate | 當前進度 | number | - |
| rate | 目標進度 | *number | string* |
| size | 圓環直徑,預設單位為 px | *number | string* |
| color | 進度條顏色,傳入物件格式可以定義漸變色 | *string | object* |
| layer-color | 軌道顏色 | string | white | | fill | 填充顏色 | string | none | | speed | 動畫速度(單位為 rate/s) | number | string | 0 | | text | 文字 | string | - | | stroke-width | 進度條寬度 | number | string | 40 | | stroke-linecap | 進度條端點的形狀,可選值為 square``butt | string | round | | clockwise | 是否順時針增加 | boolean | true | | start-position | 進度起始位置,可選值為 left、right、bottom | CircleStartPosition | top |
Slots
| 名稱 | 說明 |
|---|---|
| default | 自訂文字內容 |
類型定義
元件匯出以下類型定義:
import type { CircleProps, CircleStartPosition } from'vant';主題定制
樣式變數
元件提供了下列 CSS 變數,可用於自訂樣式,使用方法請參考 ConfigProvider 元件。
| 名稱 | 預設值 | 描述 |
|---|---|---|
| --van-circle-size | 100px | - |
| --van-circle-color | var(--van-primary-color) | - |
| --van-circle-layer-color | var(--van-white) | - |
| --van-circle-text-color | var(--van-text-color) | - |
| --van-circle-text-font-weight | var(--van-font-bold) | - |
| --van-circle-text-font-size | var(--van-font-size-md) | - |
| --van-circle-text-line-height | var(--van-line-height-md) | - |
最佳實踐
進度展示原則
設計環形進度條時,應該遵循以下原則 🎯:
<!-- ✅ 推薦:清晰的進度資訊展示 -->
<van-circle
v-model:current-rate="currentRate"
:rate="targetRate"
:speed="100"
:text="progressText"
color="#1989fa"
/>
<!-- ❌ 避免:過快的動畫速度影響使用者體驗 -->
<van-circle
:rate="100"
:speed="1000"
text="瞬間完成"
/>動畫速度控制
合理的動畫速度能提升使用者體驗 ⚡:
// ✅ 推薦:根據進度差值調整動畫速度
const calculateSpeed = (currentRate, targetRate) => {
const diff = Math.abs(targetRate - currentRate);
if (diff <= 10) return 50; // 小幅變化,慢速動畫
if (diff <= 50) return 100; // 中等變化,中速動畫
return 200; // 大幅變化,快速動畫
};
// 動態調整動畫速度
const animationSpeed = computed(() =>
calculateSpeed(currentRate.value, targetRate.value)
);文字內容設計
<!-- 多樣化的文字展示 -->
<van-circle v-model:current-rate="currentRate" :rate="80">
<template #default>
<div class="circle-text">
<div class="percentage">{{ Math.round(currentRate) }}%</div>
<div class="label">已完成</div>
</div>
</template>
</van-circle>
<style>
.circle-text {
text-align: center;
}
.percentage {
font-size: 18px;
font-weight: bold;
color: #1989fa;
}
.label {
font-size: 12px;
color: #969799;
margin-top: 4px;
}
</style>效能最佳化小貼士
動畫效能最佳化
最佳化環形進度條的動畫效能 🚀:
// ✅ 推薦:使用 requestAnimationFrame 最佳化動畫
const smoothProgress = ref(0);
const targetProgress = ref(0);
const animateProgress = () => {
const diff = targetProgress.value - smoothProgress.value;
if (Math.abs(diff) < 0.1) {
smoothProgress.value = targetProgress.value;
return;
}
smoothProgress.value += diff * 0.1;
requestAnimationFrame(animateProgress);
};
// 監聽目標進度變化
watch(targetProgress, () => {
animateProgress();
});記憶體管理
// 元件卸載時清理定時器
onUnmounted(() => {
if (animationTimer) {
clearInterval(animationTimer);
}
});設計建議
視覺設計
- 尺寸選擇:根據內容重要性選擇合適尺寸 📐
- 顏色搭配:使用品牌色或語義化顏色 🎨
- 對比度:確保進度條與背景有足夠對比度 👁️
- 動畫流暢:保持動畫的連貫性和自然感 🌊
互動體驗
- 即時回饋:進度變化應有即時的視覺回饋 ⚡
- 狀態清晰:不同狀態應有明確的視覺區分 🚦
- 資訊完整:提供必要的進度資訊和狀態說明 📊
常見問題解決
Q: 如何實現分段式進度條?
<van-circle
v-model:current-rate="currentRate"
:rate="segmentRate"
:color="segmentColor"
:text="segmentText"
/>
<script>
const segments = [
{ rate: 25, color: '#ff4444', text: '初級' },
{ rate: 50, color: '#ffaa00', text: '中級' },
{ rate: 75, color: '#00aa00', text: '高級' },
{ rate: 100, color: '#0066ff', text: '專家' }
];
const currentSegment = computed(() =>
segments.find(seg => currentRate.value <= seg.rate) || segments[segments.length - 1]
);
const segmentRate = computed(() => currentSegment.value.rate);
const segmentColor = computed(() => currentSegment.value.color);
const segmentText = computed(() => currentSegment.value.text);
</script>Q: 如何實現多個進度條的同步動畫?
<div class="progress-group">
<van-circle
v-for="(item, index) in progressItems"
:key="index"
v-model:current-rate="item.currentRate"
:rate="item.targetRate"
:speed="animationSpeed"
:color="item.color"
:text="item.text"
/>
</div>
<script>
const startSyncAnimation = () => {
progressItems.forEach((item, index) => {
setTimeout(() => {
item.targetRate = item.finalRate;
}, index * 200); // 錯開動畫時間
});
};
</script>Q: 如何實現進度條的暫停和恢復?
const isPaused = ref(false);
const pausedRate = ref(0);
const pauseProgress = () => {
isPaused.value = true;
pausedRate.value = currentRate.value;
};
const resumeProgress = () => {
isPaused.value = false;
currentRate.value = pausedRate.value;
};
// 監聽暫停狀態
watch(isPaused, (paused) => {
if (paused) {
// 暫停動畫邏輯
} else {
// 恢復動畫邏輯
}
});進階用法範例
儀表板樣式進度條
<template>
<div class="dashboard-circle">
<van-circle
v-model:current-rate="currentRate"
:rate="targetRate"
:size="200"
:stroke-width="20"
:color="dashboardColor"
layer-color="#f0f0f0"
start-position="bottom"
>
<div class="dashboard-content">
<div class="value">{{ Math.round(currentRate) }}</div>
<div class="unit">km/h</div>
<div class="label">當前速度</div>
</div>
</van-circle>
</div>
</template>
<style>
.dashboard-content {
text-align: center;
}
.value {
font-size: 32px;
font-weight: bold;
color: #333;
}
.unit {
font-size: 14px;
color: #666;
margin-top: 4px;
}
.label {
font-size: 12px;
color: #999;
margin-top: 8px;
}
</style>技能熟練度展示
<template>
<div class="skill-progress">
<van-circle
v-for="skill in skills"
:key="skill.name"
v-model:current-rate="skill.currentRate"
:rate="skill.level"
:size="80"
:color="skill.color"
:text="skill.name"
class="skill-item"
/>
</div>
</template>
<script>
const skills = ref([
{ name: 'Vue', level: 90, currentRate: 0, color: '#4fc08d' },
{ name: 'React', level: 75, currentRate: 0, color: '#61dafb' },
{ name: 'Angular', level: 60, currentRate: 0, color: '#dd0031' }
]);
</script>相關元件
- Progress 進度條 - 線性進度展示
- Loading 載入 - 載入狀態指示
- Skeleton 骨架屏 - 內容載入佔位
- Steps 步驟條 - 步驟流程展示