利用Vue實(shí)現(xiàn)卡牌翻轉(zhuǎn)的特效
前言
今天是正月初九,也是活動(dòng)的倒數(shù)第二天,復(fù)工都三天了,而我三篇春節(jié)文章還沒(méi)寫(xiě)完,實(shí)在是太混了!這次帶來(lái)的是一個(gè)春節(jié)抽???yè)面,采用卡牌翻轉(zhuǎn)的形式。

實(shí)現(xiàn)
以下所有的實(shí)現(xiàn)都是基于Vue2 來(lái)編寫(xiě)的。 (別罵了,我這就去學(xué) Vue3
鼠標(biāo)移入選中效果
從上面的效果圖可以看到,當(dāng)鼠標(biāo)移動(dòng)到某張??ǖ臅r(shí)候,這張??ň蜁?huì)放大,其余未被選中的卡片就會(huì)縮小且變得模糊。這樣的視覺(jué)效果是通過(guò) CSS 和 JS 一起控制的。
其實(shí)只用 css 也可以達(dá)到類似的效果,但在細(xì)節(jié)上做的不是很好,只要我移動(dòng)到wrap區(qū)域中,就會(huì)變得模糊,這個(gè)方案忽略了卡片與卡片之間的間隙,移入效果并沒(méi)有精準(zhǔn)地落到某個(gè)具體的卡片上,效果就像我下面展示的這樣。如果有更好的只用CSS的方案可以底下評(píng)論區(qū)交流一下!
// 沒(méi)有被hover的卡片變模糊
.wrap:hover .card{
filter: blur(25px);
transform: scale(.6);
}
// hover卡片放大
.card:hover {
transform: scale(1.3);
filter: none;
}
因此我們需要 JS 來(lái)一起控制。
先來(lái)簡(jiǎn)單看一下 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í)候就會(huì)觸發(fā)事件,且只會(huì)觸發(fā)一次。
數(shù)據(jù)如下所示,其中 cards 存儲(chǔ)卡片數(shù)據(jù)的數(shù)組,hoverId 表示當(dāng)前鼠標(biāo)選中的卡片的id,beginHover 表示鼠標(biāo)是否開(kāi)始接觸到卡片。
data(){
return {
cards: [
{id:0,content:'開(kāi)工大吉',isTurned:false},
{id:1,content:'開(kāi)工大吉',isTurned:false},
{id:2,content:'開(kāi)工大吉',isTurned:false},
{id:3,content:'開(kāi)工大吉',isTurned:false},
{id:4,content:'開(kāi)工大吉',isTurned:false}
],
hoverId: -1,
beginHover: false,
}
},再來(lái)看看兩個(gè)函數(shù)。其中 hoverItem 函數(shù)控制鼠標(biāo)移入選中的卡片。我這里的設(shè)置是,若游戲結(jié)束了,則不再有任何的效果,因此需要事先判斷下游戲是否結(jié)束。若沒(méi)有結(jié)束,修改當(dāng)前選中的卡片id與beginHover,表示可以開(kāi)始變模糊了。
hoverItem(item){
if(!this.gameOver){
this.hoverId = item.id
this.beginHover = true
}
},
reset(){
this.beginHover = false
},// 沒(méi)有被hover的卡片變模糊
.blur {
filter: blur(25px);
transform: scale(.6);
}
// hover卡片放大
.card:hover {
transform: scale(1.3);
filter: none;
}概括一下就是,當(dāng)鼠標(biāo)第一次移入卡片中,這張卡片就會(huì)放大且不會(huì)添加濾鏡,而其余未接觸到的卡片都會(huì)添加 blur 類,縮放并變得模糊。
卡片翻轉(zhuǎn)效果
PS:本文中的正面指的是封面,即有一個(gè)福字的。
卡片翻轉(zhuǎn)需要兩個(gè) div 來(lái)控制,分別是正面和背面。
當(dāng)點(diǎn)擊的時(shí)候,通過(guò)修改 transform 屬性來(lái)控制卡片的旋轉(zhuǎn),即設(shè)置 perspective 和 rotateY 來(lái)完成。旋轉(zhuǎn)過(guò)來(lái)之后,若沒(méi)有背面,我們可以看到“正面的背面”,他是沒(méi)有內(nèi)容的,因此需要設(shè)置我們自己背面的背景色來(lái)覆蓋掉,并寫(xiě)入文本。這里需要注意的是,我們的背面也需要再繞Y軸旋轉(zhuǎn)一次,不然看來(lái)的內(nèi)容仍是相反的。
那么如何讓翻轉(zhuǎn)效果看起來(lái)更協(xié)調(diào)呢,這里我的想法是,控制背面的背景色與封面保持一致,通過(guò)設(shè)置 setTimeout 函數(shù)讓背面的內(nèi)容晚點(diǎn)出來(lái),以造成是我翻轉(zhuǎn)卡片到某個(gè)角度后才能看見(jiàn)背面的文字。至于延時(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)動(dòng)畫(huà)我設(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:'開(kāi)工大吉',isTurned:false},
{id:1,content:'開(kāi)工大吉',isTurned:false},
{id:2,content:'開(kāi)工大吉',isTurned:false},
{id:3,content:'開(kāi)工大吉',isTurned:false},
{id:4,content:'開(kāi)工大吉',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會(huì)出現(xiàn)圖片大小變化div外層不變
}
// 沒(méi)有被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é)束,未翻開(kāi)的牌自動(dòng)翻開(kāi)向下移動(dòng)
.gameOver {
transform: perspective(900px) rotateY(180deg) scale(1) translateY(50%);
cursor: default;
}
}
}
</style>結(jié)語(yǔ)
以上就是一個(gè)翻轉(zhuǎn)福卡的頁(yè)面,但是在寫(xiě)文章梳理的時(shí)候發(fā)現(xiàn)有一些邏輯還是比較繞的,可能我自己設(shè)置了一些沒(méi)必要的約束吧。
到此這篇關(guān)于利用Vue實(shí)現(xiàn)卡牌翻轉(zhuǎn)的特效的文章就介紹到這了,更多相關(guān)Vue卡牌翻轉(zhuǎn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue scroller返回頁(yè)面記住滾動(dòng)位置的實(shí)例代碼
這篇文章主要介紹了vue scroller返回頁(yè)面記住滾動(dòng)位置的實(shí)例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-01-01
Vite配置代理Proxy解決跨域問(wèn)題小結(jié)
我們?cè)谧鲰?xiàng)目的時(shí)候經(jīng)常會(huì)遇到跨域的問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于Vite配置代理Proxy解決跨域問(wèn)題的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-03-03
Vue源碼解析之?dāng)?shù)組變異的實(shí)現(xiàn)
這篇文章主要介紹了Vue源碼解析之?dāng)?shù)組變異的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12
vue?請(qǐng)求后端數(shù)據(jù)的示例代碼
在vue中,我們?nèi)绾瓮ㄟ^(guò)請(qǐng)求接口來(lái)訪問(wèn)后端的數(shù)據(jù)呢?在這里簡(jiǎn)單總結(jié)了一個(gè)小示例,對(duì)vue請(qǐng)求后端數(shù)據(jù)實(shí)例代碼感興趣的朋友一起看看吧2022-09-09
Vue Spa切換頁(yè)面時(shí)更改標(biāo)題的實(shí)例代碼
本篇文章主要介紹了Vue Spa切換頁(yè)面時(shí)更改標(biāo)題的實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07
Vue 組件參數(shù)校驗(yàn)與非props特性的方法
這篇文章主要介紹了Vue 組件參數(shù)校驗(yàn)與非props特性的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-02-02
Vue中動(dòng)態(tài)Class實(shí)戰(zhàn)示例
這篇文章主要為大家介紹了Vue中動(dòng)態(tài)Class的實(shí)戰(zhàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11

