在今天的實作中,我們將用 Vue.js 和動畫效果來實現一個超酷的行星選擇器!
透過點擊文字,我們可以淡入淡出不同的星球圖片,讓頁面充滿科幻氛圍。這不僅是一個有趣的小專案,還能幫助你學習如何在 Vue.js 中實現動畫效果、圖片切換、以及如何透過 textPath
來呈現獨特的文字排版。
這次專案的設計核心是結合 Vue.js 的動畫管理和 SVG 的文字排版,透過文字與圖片的交互來打造一個可點擊、動態過渡的星球切換效果。整個過程包括:
SVG textPath
來創建一條可隨著曲線排列的行星名稱文字路徑。transition
元件實現行星圖片的淡入淡出效果。在這個專案中,我們將行星選擇器與圖片顯示邏輯分離成獨立的 Vue 組件。這樣的設計有助於提升專案的可維護性和可擴展性。每個組件只負責它該做的工作,父元件管理狀態和主要邏輯,子元件負責具體的呈現。
在父元件中,我們使用 Vue 的 ref
和 computed
來管理行星的狀態和動態數據。
const activeIndex = ref(0); // 當前選中的行星索引
const currentPlanet = computed(() =%3E planets[activeIndex.value]); // 計算當前行星的資料
這裡使用 computed
來動態計算當前的行星資料,當 activeIndex
改變時,currentPlanet
會自動更新並傳遞到子元件顯示對應的圖片。這樣的設計可以減少不必要的重複邏輯,確保程式碼乾淨且易於維護。
在 PlanetNav
子元件中,我們使用 SVG
和 textPath
來實現文字的環繞排版,這是一種獨特且強大的設計手段,特別適合製作圓形或曲線上的文字排列。
%3Csvg viewBox="0 0 400 500" xmlns="http://www.w3.org/2000/svg">
<path id="navPath" d="M10,250 C30,0 370,0 390,250" fill="none" />
<text>
<textPath href="#navPath" :startOffset="getOffset" class="transition-all duration-1000 ease-out">
<tspan v-for="(planet, index) in planets" :key="planet.id"
@click="handleClick(index)"
class="cursor-pointer pointer-events-auto fill-white opacity-60 hover:opacity-100"
:style="getStyle(index)">
{{ planet.title }}
</tspan>
</textPath>
</text>
</svg>
技術重點:SVG textPath
textPath
是 SVG 提供的一個強大功能,它允許我們將文字沿著路徑排列。在這裡,textPath
使行星名稱沿著一條曲線排列,營造出環繞感。同時,透過 tspan
元素來分別渲染每個行星名稱,並且每個行星名稱都有一個點擊事件,觸發行星圖片的切換。
點擊事件與過渡動畫
當使用者點擊某個行星名稱時,會觸發 handleClick
函數,這個函數會改變 activeIndex
,並且使用 emit
通知父元件更新當前行星狀態:
const handleClick = (index: number) => {
activeIndex.value = index;
emit("change", index); // 通知父元件切換行星
};
這樣的設計讓我們能夠保持父子元件之間的狀態同步,並且確保每次點擊事件的變更都會觸發圖片的過渡動畫。
這次的動畫實作中,圖片切換的效果是通過 Vue 的 transition
元件來實現的,搭配自定義的淡入淡出動畫來提升過渡的視覺體驗。
<transition name="fade" mode="out-in">
<figure v-if="currentPlanet" :key="currentPlanet.id">
<img :src="currentPlanet.image" alt="current planet"
:style="getPlanetStyle(currentPlanet)"
class="max-w-full fixed bottom-0 left-1/2 h-[50vh] transform -translate-x-1/2" />
</figure>
</transition>
在這裡,我們通過 transition
元件來處理圖片的進場與退場效果。mode="out-in"
確保圖片的進出順序為先淡出舊圖片,再淡入新圖片。這樣的順序可以避免圖片重疊造成的視覺干擾。
淡入淡出動畫實現:
.fade-enter-active, .fade-leave-active {
transition: opacity 1s ease;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
.fade-enter-to, .fade-leave-from {
opacity: 1;
}
這段 CSS 實現了圖片的淡入淡出過渡,讓圖片從完全透明到完全顯示之間有一個平滑的過程。1s ease
的過渡時間使整個切換動畫看起來更加柔和,提升了視覺體驗。
我們還對行星圖片進行了部分裁切,讓星球只顯示其上半部分,這樣的視覺效果讓星球看起來像是懸浮在畫面中。
const getPlanetStyle = (planet: Planet) => ({
height: planet.customHeight,
transform: 'translateX(-50%) translateY(50%)', // 向下移動裁剪掉的高度
clipPath: 'inset(0 0 50% 0)', // 裁切掉下半部分
});
這裡的 clipPath
是一個 CSS 屬性,用來裁剪元素的可見部分。inset(0 0 50% 0)
意味著我們將圖片的下半部分裁切掉,只保留上半部分的視覺效果。
在這個專案中,我們利用 Vue 的反應式數據來動態計算每個行星的相對位置與動畫效果。例如,行星名稱會根據當前的選中狀態來動態改變其旋轉角度,這種動畫效果通過 transform
和 transition
來實現。
<tspan :style="{ transform: `rotate(${activeIndex === index ? 0 : index * 45}deg)`, transition: 'transform 1s ease' }">
{{ planet.title }}
</tspan>
這段程式碼根據行星的索引來動態改變文字的旋轉角度,並且當前選中的行星會保持 rotate(0deg)
,也就是不旋轉的狀態。這樣的效果使得當使用者點擊行星名稱時,文字會進行微妙的動畫改變,增加了互動性。
透過這次的實作,我們學習了如何將動畫效果與 Vue.js 的組件化設計相結合,
並且利用 SVG 的強大功能來呈現文字與圖片的交互效果。整個專案展示了如何在前端專案中平衡動態效果和性能優化,並且通過精巧的設計讓頁面更加生動。
希望這篇文章能幫助你更深入地理解 Vue.js 中的動畫管理與 SVG 的應用技巧,並且激發你在未來的專案中運用這些技術來創造更多有趣的互動效果!🌍✨
快來動手實作屬於你自己的宇宙星球展示頁面吧!🚀