今天,我們將用 Vue.js 和 TypeScript 實現一個充滿趣味的翻牌遊戲,讓你不僅能挑戰自己的記憶力,還能學到豐富的前端技術知識。這篇文章會深入探討每一個技術細節,讓你在實作過程中真正掌握 Vue.js 和 TypeScript 的精髓。
這次設計的核心概念是動態翻轉效果 + 卡片配對遊戲。我們通過組件化的方式,把卡片的翻轉效果、配對邏輯和遊戲狀態管理獨立實現。每張卡片都可以通過 props
接收父元件的狀態,並利用 CSS 的 3D 翻轉效果來呈現出流暢的翻牌動畫。
ref
、props
和 computed
高效地管理遊戲狀態。perspective
和 transform-style
創造真實的翻轉視覺效果。setTimeout
和狀態管理來控制遊戲的流暢性。我們先從卡片翻轉的動畫效果開始,這裡使用了一個名為 FlipCard
的子組件,每張卡片都可以通過 isFlipped
來控制是否翻轉。
FlipCard
設計在 Vue.js 中,我們經常將可重複使用的功能拆分為獨立的組件。這樣可以提高專案的模組化程度,也便於重複使用和測試。
props
控制卡片狀態<script lang="ts" setup>
import { defineProps } from 'vue';
const props = defineProps({
isFlipped: Boolean,
});
</script>
這段程式碼使用了 defineProps
來接收來自父元件的 isFlipped
屬性。透過 TypeScript 的類型註解,確保 isFlipped
屬性只能是布林值,這樣在使用時會有更好的開發體驗和錯誤提示。
卡片的翻轉效果主要是通過 CSS 來實現的。我們在容器上應用了 perspective
,這樣可以讓翻轉效果更具立體感:
<div class="cursor-pointer w-full h-full [perspective:800px]">
<div
class="card h-full w-full relative [transition:transform_1.5s] [transform-style:preserve-3d]"
:class="{ '[transform:rotateY(180deg)]': props.isFlipped }"
>
<!-- 卡片的正面和背面 -->
</div>
</div>
perspective: 800px
:設置透視效果,使翻轉時具有真實的空間感。transform-style: preserve-3d
:保留 3D 效果,使子元素在 3D 空間中渲染。transition: transform 1.5s
:設置過渡效果,讓卡片在翻轉時更為平滑。當 props.isFlipped
為 true
時,卡片會添加 rotateY(180deg)
的樣式,實現翻轉。
接下來,我們來看父元件中如何管理卡片的狀態以及處理卡片配對的邏輯。
我們從一組動物表情符號中隨機選擇 12 個,並將它們各自複製一份以生成配對,然後打亂順序:
const animals = ['😺', '😸', ...];
const shuffledEmojis = [...animals].sort(() => Math.random() - 0.5);
const cardBackEmoji = shuffledEmojis[0]; // 背面的表情符號
const animalItems = animals.slice(1, 13);
const selectedAnimals = ref([...animalItems, ...animalItems]); // 生成配對卡片
這段程式碼隨機選擇了 12 種動物表情符號,並將它們各複製一份生成 24 張卡片。這樣的設計可以確保遊戲中每個表情符號都有一個配對。
ref
管理遊戲狀態在 Vue.js 中,ref
可以用來管理組件的反應式狀態。以下是我們在遊戲中管理卡片狀態的方式:
const pairCards = ref<string[]>([]); // 儲存當前翻開的卡片
const pairIndexs = ref<number[]>([]); // 儲存翻開卡片的索引
const flippedStates = ref<boolean[]>(selectedAnimals.value.map(() => false)); // 追蹤每張卡片的翻開狀態
這裡,我們使用 pairCards
來儲存翻開的卡片內容,pairIndexs
來儲存翻開卡片的索引,並使用 flippedStates
來追蹤每張卡片的翻開狀態。
const checkCard = (animal: string, index: number) => {
if (flippedStates.value[index]) return; // 防止重複翻開已經翻轉的卡片
pairCards.value.push(animal);
pairIndexs.value.push(index);
flippedStates.value[index] = true; // 翻開卡片
if (pairCards.value.length === 2) {
if (compareAnimals(pairCards.value[0], pairCards.value[1])) {
// 配對成功
pairCards.value = [];
pairIndexs.value = [];
console.log('match');
} else {
// 配對失敗後翻回卡片
setTimeout(() => {
flippedStates.value[pairIndexs.value[0]] = false;
flippedStates.value[pairIndexs.value[1]] = false;
pairCards.value = [];
pairIndexs.value = [];
console.log('not match');
}, 1000); // 延遲 1 秒後翻回
}
}
};
這段程式碼負責檢查卡片配對的結果:
flippedStates.value[index]
,確保不會再次翻開已經翻開的卡片。setTimeout
延遲 1 秒將卡片翻回去。這樣的設計使遊戲不會過於倉促,給玩家一點時間記住卡片的位置。
在整個遊戲邏輯中,我們利用 TypeScript 來強化變數和函數的類型註解,避免類型錯誤。例如:
const compareAnimals = (animal1: string, animal2: string): boolean => {
return animal1 === animal2;
};
這樣的類型註解可以保證我們的函數在處理不同類型的變數時不會出現錯誤,從而提高遊戲的穩定性和維護性。
這次的翻牌遊戲實作,我們用 Vue.js 和 TypeScript 創造出了一個視覺效果驚豔且充滿趣味的遊戲。
透過 Vue.js 的組件化設計、CSS 3D 翻轉效果和 TypeScript 的類型安全,我們不僅讓遊戲看起來精緻流暢,還能確保程式碼的可讀性與可維護性。
希望這篇深入的技術教學能幫助你更好地理解 Vue.js 和 TypeScript 的使用技巧,並激發你在前端開發上的創意靈感!🎮✨