利用Vue實(shí)現(xiàn)卡牌翻轉(zhuǎn)的特效
前言
今天是正月初九,也是活動的倒數(shù)第二天,復(fù)工都三天了,而我三篇春節(jié)文章還沒寫完,實(shí)在是太混了!這次帶來的是一個(gè)春節(jié)抽??撁妫捎每ㄅ品D(zhuǎn)的形式。
實(shí)現(xiàn)
以下所有的實(shí)現(xiàn)都是基于Vue2 來編寫的。 (別罵了,我這就去學(xué) Vue3
鼠標(biāo)移入選中效果
從上面的效果圖可以看到,當(dāng)鼠標(biāo)移動到某張??ǖ臅r(shí)候,這張??ň蜁糯?,其余未被選中的卡片就會縮小且變得模糊。這樣的視覺效果是通過 CSS 和 JS 一起控制的。
其實(shí)只用 css 也可以達(dá)到類似的效果,但在細(xì)節(jié)上做的不是很好,只要我移動到wrap區(qū)域中,就會變得模糊,這個(gè)方案忽略了卡片與卡片之間的間隙,移入效果并沒有精準(zhǔn)地落到某個(gè)具體的卡片上,效果就像我下面展示的這樣。如果有更好的只用CSS的方案可以底下評論區(qū)交流一下!
// 沒有被hover的卡片變模糊 .wrap:hover .card{ filter: blur(25px); transform: scale(.6); } // hover卡片放大 .card:hover { transform: scale(1.3); filter: none; }
因此我們需要 JS 來一起控制。
先來簡單看一下 html 結(jié)構(gòu),這里我把一些不需要的代碼先去掉了。
<div class="wrap"> <div class="card cover" v-for="item in cards" :key="item.id" :class="{ 'blur': item.id != hoverId && beginHover, }" @mouseenter="hoverItem(item)" @mouseout="reset()"> </div> </div>
在上面的代碼中,@mouseenter
和 @mouseout
表示鼠標(biāo)移入移出事件,但鼠標(biāo)移入該 div
的時(shí)候就會觸發(fā)事件,且只會觸發(fā)一次。
數(shù)據(jù)如下所示,其中 cards
存儲卡片數(shù)據(jù)的數(shù)組,hoverId
表示當(dāng)前鼠標(biāo)選中的卡片的id,beginHover
表示鼠標(biāo)是否開始接觸到卡片。
data(){ return { cards: [ {id:0,content:'開工大吉',isTurned:false}, {id:1,content:'開工大吉',isTurned:false}, {id:2,content:'開工大吉',isTurned:false}, {id:3,content:'開工大吉',isTurned:false}, {id:4,content:'開工大吉',isTurned:false} ], hoverId: -1, beginHover: false, } },
再來看看兩個(gè)函數(shù)。其中 hoverItem
函數(shù)控制鼠標(biāo)移入選中的卡片。我這里的設(shè)置是,若游戲結(jié)束了,則不再有任何的效果,因此需要事先判斷下游戲是否結(jié)束。若沒有結(jié)束,修改當(dāng)前選中的卡片id與beginHover
,表示可以開始變模糊了。
hoverItem(item){ if(!this.gameOver){ this.hoverId = item.id this.beginHover = true } }, reset(){ this.beginHover = false },
// 沒有被hover的卡片變模糊 .blur { filter: blur(25px); transform: scale(.6); } // hover卡片放大 .card:hover { transform: scale(1.3); filter: none; }
概括一下就是,當(dāng)鼠標(biāo)第一次移入卡片中,這張卡片就會放大且不會添加濾鏡,而其余未接觸到的卡片都會添加 blur
類,縮放并變得模糊。
卡片翻轉(zhuǎn)效果
PS:本文中的正面指的是封面,即有一個(gè)福字的。
卡片翻轉(zhuǎn)需要兩個(gè) div
來控制,分別是正面和背面。
當(dāng)點(diǎn)擊的時(shí)候,通過修改 transform
屬性來控制卡片的旋轉(zhuǎn),即設(shè)置 perspective
和 rotateY
來完成。旋轉(zhuǎn)過來之后,若沒有背面,我們可以看到“正面的背面”,他是沒有內(nèi)容的,因此需要設(shè)置我們自己背面的背景色來覆蓋掉,并寫入文本。這里需要注意的是,我們的背面也需要再繞Y軸旋轉(zhuǎn)一次,不然看來的內(nèi)容仍是相反的。
那么如何讓翻轉(zhuǎn)效果看起來更協(xié)調(diào)呢,這里我的想法是,控制背面的背景色與封面保持一致,通過設(shè)置 setTimeout
函數(shù)讓背面的內(nèi)容晚點(diǎn)出來,以造成是我翻轉(zhuǎn)卡片到某個(gè)角度后才能看見背面的文字。至于延時(shí)多久呢,這就慢慢調(diào)了哈哈。
.back { position: absolute; width: 100%; height: 100%; left: 0; background: rgb(168, 10, 3); transform: rotateY(180deg); // 還是需要旋轉(zhuǎn) font-size: 1rem; color: #f1c40f; border-radius: 10px; display: flex; justify-content: center; align-items: center; }
翻轉(zhuǎn)動畫我設(shè)置的1s,延時(shí)用了400ms。
setTimeout(() => { this.back = true }, 400);
完整代碼
<template> <div class="the-card"> <div class="wrap"> <div class="card cover" v-for="item in cards" :key="item.id" :class="{ 'cardHover': !gameOver, 'blur': item.id != hoverId && beginHover, 'turned': item.isTurned, 'gameOver': !item.isTurned && gameOver, }" @mouseenter="hoverItem(item)" @mouseout="reset()" @click="turnItem(item)"> <div :class="{'back':back}" v-if="back"> <span>{{item.content}}</span> </div> </div> </div> </div> </template> <script> export default { data(){ return { cards: [ {id:0,content:'開工大吉',isTurned:false}, {id:1,content:'開工大吉',isTurned:false}, {id:2,content:'開工大吉',isTurned:false}, {id:3,content:'開工大吉',isTurned:false}, {id:4,content:'開工大吉',isTurned:false} ], hoverId: -1, beginHover: false, gameOver: false, back: false } }, methods: { hoverItem(item){ if(!this.gameOver){ this.hoverId = item.id this.beginHover = true } }, reset(){ this.beginHover = false }, turnItem(item){ if(this.gameOver) return this.cards.map(card => { card.id === item.id ? card.isTurned = true : ""; }) setTimeout(() => { this.beginHover = false this.gameOver = true }, 300); setTimeout(() => { this.back = true }, 400); } }, created(){ let randomNum = Math.floor(Math.random() * 5) this.cards[randomNum].content = '恭喜您獲得【冰墩墩】' } } </script> <style lang="less" scoped> .the-card { height: 100vh; background-color: #bdc3c7; display: flex; justify-content: center; align-items: center; overflow: hidden; .wrap { width: 100%; display: flex; justify-content: center; align-items: center; .card { width: 180px; height: 300px; margin: 0 1rem; transition: 1s; cursor: pointer; border-radius: 10px; position: relative; } // ??ǚ饷? .cover { background: url(../assets/fu.jpg) center center no-repeat; background-size: 100% 100%; // 用contain會出現(xiàn)圖片大小變化div外層不變 } // 沒有被hover的卡片變模糊 .blur { filter: blur(25px); transform: scale(.6); } // 卡片點(diǎn)擊翻轉(zhuǎn) .turned { box-shadow: 0px 0px 20px 10px #f1c40f; transform: perspective(900px) rotateY(180deg) scale(1) translateY(-50%); } // hover卡片放大,游戲結(jié)束后失效 .cardHover:not(.turned):hover { transform: scale(1.3); filter: none; } .back { position: absolute; width: 100%; height: 100%; left: 0; background: rgb(168, 10, 3); transform: rotateY(180deg); font-size: 1rem; color: #f1c40f; border-radius: 10px; display: flex; justify-content: center; align-items: center; } // 游戲結(jié)束,未翻開的牌自動翻開向下移動 .gameOver { transform: perspective(900px) rotateY(180deg) scale(1) translateY(50%); cursor: default; } } } </style>
結(jié)語
以上就是一個(gè)翻轉(zhuǎn)??ǖ捻撁?,但是在寫文章梳理的時(shí)候發(fā)現(xiàn)有一些邏輯還是比較繞的,可能我自己設(shè)置了一些沒必要的約束吧。
到此這篇關(guān)于利用Vue實(shí)現(xiàn)卡牌翻轉(zhuǎn)的特效的文章就介紹到這了,更多相關(guān)Vue卡牌翻轉(zhuǎn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue+vuex+axio從后臺獲取數(shù)據(jù)存入vuex實(shí)現(xiàn)組件之間共享數(shù)據(jù)
這篇文章主要介紹了vue+vuex+axio從后臺獲取數(shù)據(jù)存入vuex,組件之間共享數(shù)據(jù),非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-04-04vue?實(shí)現(xiàn)動態(tài)設(shè)置元素的高度
這篇文章主要介紹了在vue中實(shí)現(xiàn)動態(tài)設(shè)置元素的高度,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08ElementUI 修改默認(rèn)樣式的幾種辦法(小結(jié))
這篇文章主要介紹了ElementUI 修改默認(rèn)樣式的幾種辦法(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07vue3+ts+elementPLus實(shí)現(xiàn)v-preview指令
本文主要介紹了vue3+ts+elementPLus實(shí)現(xiàn)v-preview指令,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05