iT邦幫忙

2024 iThome 鐵人賽

DAY 28
0
Modern Web

創意前端設計:用 Vue.js 打造 30 個互動實用功能系列 第 28

Day 28 Vue.js 動效分類實戰 (19) 星球特輯 - 把宇宙裝進你的網頁

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20241012/20124462zmHFGOGzZZ.jpg


從行星選擇到動畫過渡,揭開星球切換背後的技術秘密

在今天的實作中,我們將用 Vue.js 和動畫效果來實現一個超酷的行星選擇器!
透過點擊文字,我們可以淡入淡出不同的星球圖片,讓頁面充滿科幻氛圍。這不僅是一個有趣的小專案,還能幫助你學習如何在 Vue.js 中實現動畫效果、圖片切換、以及如何透過 textPath 來呈現獨特的文字排版。

https://ithelp.ithome.com.tw/upload/images/20241012/20124462bbVqoUNzRI.png

設計核心概念

這次專案的設計核心是結合 Vue.js 的動畫管理和 SVG 的文字排版,透過文字與圖片的交互來打造一個可點擊、動態過渡的星球切換效果。整個過程包括:

  1. 使用 SVG textPath 來創建一條可隨著曲線排列的行星名稱文字路徑。
  2. 使用 Vue.js 的 transition 元件實現行星圖片的淡入淡出效果。
  3. 動態控制圖片的顯示與裁切,根據使用者點擊文字來切換對應的行星圖片。

讓宇宙盡在掌控中

1. 組件化設計的優勢

在這個專案中,我們將行星選擇器與圖片顯示邏輯分離成獨立的 Vue 組件。這樣的設計有助於提升專案的可維護性和可擴展性。每個組件只負責它該做的工作,父元件管理狀態和主要邏輯,子元件負責具體的呈現。

父元件:管理狀態與圖片切換

在父元件中,我們使用 Vue 的 refcomputed 來管理行星的狀態和動態數據。

const activeIndex = ref(0); // 當前選中的行星索引
const currentPlanet = computed(() =%3E planets[activeIndex.value]); // 計算當前行星的資料

這裡使用 computed 來動態計算當前的行星資料,當 activeIndex 改變時,currentPlanet 會自動更新並傳遞到子元件顯示對應的圖片。這樣的設計可以減少不必要的重複邏輯,確保程式碼乾淨且易於維護。

子元件:SVG 排版與點擊事件

PlanetNav 子元件中,我們使用 SVGtextPath 來實現文字的環繞排版,這是一種獨特且強大的設計手段,特別適合製作圓形或曲線上的文字排列。

%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); // 通知父元件切換行星
};

這樣的設計讓我們能夠保持父子元件之間的狀態同步,並且確保每次點擊事件的變更都會觸發圖片的過渡動畫。

2. CSS 過渡與 3D 效果

img

這次的動畫實作中,圖片切換的效果是通過 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 的過渡時間使整個切換動畫看起來更加柔和,提升了視覺體驗。

圖片裁切與 3D 效果

https://ithelp.ithome.com.tw/upload/images/20241012/20124462FgFf4vaBO8.png
我們還對行星圖片進行了部分裁切,讓星球只顯示其上半部分,這樣的視覺效果讓星球看起來像是懸浮在畫面中。

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) 意味著我們將圖片的下半部分裁切掉,只保留上半部分的視覺效果。

3. 動態計算與動畫同步

在這個專案中,我們利用 Vue 的反應式數據來動態計算每個行星的相對位置與動畫效果。例如,行星名稱會根據當前的選中狀態來動態改變其旋轉角度,這種動畫效果通過 transformtransition 來實現。

<tspan :style="{ transform: `rotate(${activeIndex === index ? 0 : index * 45}deg)`, transition: 'transform 1s ease' }">
  {{ planet.title }}
</tspan>

這段程式碼根據行星的索引來動態改變文字的旋轉角度,並且當前選中的行星會保持 rotate(0deg),也就是不旋轉的狀態。這樣的效果使得當使用者點擊行星名稱時,文字會進行微妙的動畫改變,增加了互動性。


結語:技術與美感的完美結合

img

透過這次的實作,我們學習了如何將動畫效果與 Vue.js 的組件化設計相結合,

並且利用 SVG 的強大功能來呈現文字與圖片的交互效果。整個專案展示了如何在前端專案中平衡動態效果和性能優化,並且通過精巧的設計讓頁面更加生動。

希望這篇文章能幫助你更深入地理解 Vue.js 中的動畫管理與 SVG 的應用技巧,並且激發你在未來的專案中運用這些技術來創造更多有趣的互動效果!🌍✨

快來動手實作屬於你自己的宇宙星球展示頁面吧!🚀


上一篇
Day 27 Vue.js 動效分類實戰 (18) 整合特輯 - 技術全解析,打造精緻的卡片翻牌遊戲
下一篇
Day29 Vue.js 動效分類實戰 (20) 蛋糕特輯 - 來過生日!吹氣 + 驚喜動畫,慶祝儀式感拉滿
系列文
創意前端設計:用 Vue.js 打造 30 個互動實用功能30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言