大家好!今天是 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 鐵人賽圓滿完賽!( ̄▽ ̄)👍