
大家好!今天是 IT 鐵人賽的第三十天,真不知不覺我們已經走到了終點!
這段旅程有很多調皮又溫馨的記憶,而今天我們要終於來做一個最後的決定——將我們的設計做個完美的收尾。
今天我們會帶大家一起打造一面充滿可愛貓咪的廣告牆!
這些萌萌的貓咪圖片加上一些有趣的動態效果,讓網站瞬間變得更加生動有趣。快來跟我一起使用 Vue 3 和 UnoCSS 展現這個超級可愛的貓咪吧!

我們的核心目標是——在模糊的背景廣告牆上加入動態效果,讓廣告牆變得生動有趣,給人以動畫般的視覺體驗。這些貓咪不僅是靜止的圖片,當你移動滑鼠靠近它們時,它們會有一些有趣的小互動,例如放大和模糊效果,這些動態設計讓網站更加吸引人。在設計中,我們使用 Vue 的組件化結構與 UnoCSS 來輕鬆實現這些效果,並呈現出一個充滿活力的廣告牆。
我們將設計分成兩部分:
為了更好地理解父元件的結構,我們將其拆解為更小的步驟。以下是父元件各部分的詳細解釋:
div 來作為背景,這裡應用了背景色和固定定位來確保廣告牆佈滿全屏。然後,在內層容器中,我們使用了 flex 布局來確保所有子元件垂直排列在視窗中心。v-for 循環來生成多個 WallItem 子元件,並通過 props 傳遞數據給子元件。在這部分,我們主要專注於父元件的技術細節。
父元件的主要職責是管理整體的佈局和動態效果,並且作為所有子元件的容器。以下是父元件的實作步驟:
父元件的結構負責定義整個廣告牆的佈局,並將其置中。我們會使用 Vue 3 的 setup 語法來完成這部分的實作,並搭配 UnoCSS 進行樣式管理。
<template>
  <div class="bg-[#f7f7f7] overflow-hidden h-screen w-full fixed">
    <div
      class="flex flex-col h-[150vh] justify-center left-1/2 absolute top-1/2
        opacity-80 wrapper-images perspective-[800px] rotate-y-[-10deg] rotate-[10deg] font-mono"
    >
      <!-- 使用 ImageLine 組件,傳遞 texts props -->
      <ImageLine v-for="(texts, index) in imageLines" :key="index" :texts="texts" />
    </div>
  </div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import ImageLine from './WallItem.vue';
const imageLines = ref([
  ['賀', '賀', '賀', '賀', '賀'],
  ['賀', '賀', '賀', '賀', '賀'],
  ['恭喜', '恭喜', '恭喜', '恭喜', '恭喜'],
  ['IT鐵人', 'IT鐵人', 'IT鐵人', 'IT鐵人', 'IT鐵人'],
  ['完賽', '完賽', '完賽', '完賽', '完賽'],
  ['🥳', '🥳', '🥳', '🥳', '🥳'],
]);
</script>

在父元件中,我們使用 UnoCSS 來快速應用樣式。這樣的方式讓我們能夠輕鬆地管理全局的佈局效果,同時確保動態效果能夠順利呈現。
bg-[#f7f7f7],讓整體呈現柔和的灰色調,並使用 overflow-hidden 來避免多餘的滾動條。left-1/2 和 top-1/2 將內部容器置中,並通過 translate3d 來進行微調,使容器更精確地位於視窗中央。perspective-[800px] 來增強 3D 視覺效果,並使用 rotate-y-[-10deg] 和 rotate-[10deg] 讓廣告牆呈現出一種立體的傾斜效果。flex 和 absolute 位置調整,確保了廣告牆始終處於視覺中心。在這部分,我們將專注於子元件的技術細節。子元件的主要職責是展示具體的貓廣告內容,每個子元件都是一個廣告單元,並具有相應的動態效果。以下是子元件的實作步驟:
子元件負責展示每一張廣告圖片以及其相關的動態效果。在這個子元件中,我們會使用 props 來接收父元件傳遞的資料,並根據這些資料進行展示。
<template>
  <div class="images-line">
    <div v-for="(text, index) in texts" :key="index" class="line" :style="catBackgroundStyle">
      <div class="img" :style="catBackgroundStyle">
        <p class="wrapper-images">{{ text }}</p>
      </div>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { computed, defineProps } from 'vue';
const props = defineProps<{ texts: string[] }>();
const catBackgroundStyle = computed(() => ({
  backgroundImage: `url('@/assets/images/cat.jpeg')`,
  backgroundSize: 'cover',
  backgroundPosition: 'center',
}));
</script>
<style scoped>
.images-line {
  animation: runner var(--duration) linear infinite;
  display: flex;
  transform: translateX(23%);
}
.images-line:hover {
  animation-play-state: paused;
}
.line {
  background-position: 50% 50%;
  background-size: cover;
  flex: none;
  height: 20vh;
  margin: clamp(15px, 3vw, 30px);
  width: 20vh;
  position: relative;
  transition: ease-in-out all 0.3s;
}
.line .img {
  position: absolute;
  z-index: 2;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  background-position: 50% 50%;
  background-size: cover;
  transition: ease-in-out all 0.3s;
}
.line:hover .img {
  cursor: pointer;
  transform: scale(1.1) translateZ(0px);
}
.line:hover:after {
  filter: blur(35px) opacity(0.8);
}
.line:after {
  content: "";
  background: inherit;
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  top: 3vh;
  position: absolute;
  background-size: cover;
  z-index: -1;
  transition: ease-in-out all 0.3s;
  filter: blur(25px) opacity(0.8);
}
@keyframes runner {
  to {
    transform: translateX(-10.4%);
  }
}
</style>

transform 和 filter 屬性來實現。catBackgroundStyle 計算屬性用於設置背景圖片,這樣可以保持每個廣告單元的一致性。
子元件負責具體展示每一個廣告元素,並且通過 Vue 3 的 props 和 setup 語法來進行數據的傳遞和渲染。每個子元件的動態效果使得整個廣告牆更加生動有趣。
Wall.vue 和 WallItem.vue 兩個元件,符合現代開發的最佳實踐,這樣的組件化設計不僅提升了代碼的可重用性,也讓後續維護更加輕鬆。經過三十天的挑戰,我們終於來到了終點。
這段旅程不僅是技術上的挑戰,更是心態和毅力的磨練。
每一個小小的動態效果,每一次的佈局調整,都是對我們能力的提升。
希望大家能夠從這次挑戰中獲得成就感和滿足感,也希望未來我們能繼續一起探索更多有趣的技術領域!
感謝大家的陪伴,IT 鐵人賽圓滿完賽!( ̄▽ ̄)👍