利用Vue实现卡牌翻转的特效
作者:小陈同学吗 发布时间:2024-04-30 10:30:45
前言
今天是正月初九,也是活动的倒数第二天,复工都三天了,而我三篇春节文章还没写完,实在是太混了!这次带来的是一个春节抽福卡页面,采用卡牌翻转的形式。
实现
以下所有的实现都是基于Vue2 来编写的。 (别骂了,我这就去学 Vue3
鼠标移入选中效果
从上面的效果图可以看到,当鼠标移动到某张福卡的时候,这张福卡就会放大,其余未被选中的卡片就会缩小且变得模糊。这样的视觉效果是通过 CSS 和 JS 一起控制的。
其实只用 css 也可以达到类似的效果,但在细节上做的不是很好,只要我移动到wrap区域中,就会变得模糊,这个方案忽略了卡片与卡片之间的间隙,移入效果并没有精准地落到某个具体的卡片上,效果就像我下面展示的这样。如果有更好的只用CSS的方案可以底下评论区交流一下!
// 没有被hover的卡片变模糊
.wrap:hover .card{
filter: blur(25px);
transform: scale(.6);
}
// hover卡片放大
.card:hover {
transform: scale(1.3);
filter: none;
}
因此我们需要 JS 来一起控制。
先来简单看一下 html 结构,这里我把一些不需要的代码先去掉了。
<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
表示鼠标移入移出事件,但鼠标移入该 div
的时候就会触发事件,且只会触发一次。
数据如下所示,其中 cards
存储卡片数据的数组,hoverId
表示当前鼠标选中的卡片的id,beginHover
表示鼠标是否开始接触到卡片。
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,
}
},
再来看看两个函数。其中 hoverItem
函数控制鼠标移入选中的卡片。我这里的设置是,若游戏结束了,则不再有任何的效果,因此需要事先判断下游戏是否结束。若没有结束,修改当前选中的卡片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;
}
概括一下就是,当鼠标第一次移入卡片中,这张卡片就会放大且不会添加滤镜,而其余未接触到的卡片都会添加 blur
类,缩放并变得模糊。
卡片翻转效果
PS:本文中的正面指的是封面,即有一个福字的。
卡片翻转需要两个 div
来控制,分别是正面和背面。
当点击的时候,通过修改 transform
属性来控制卡片的旋转,即设置 perspective
和 rotateY
来完成。旋转过来之后,若没有背面,我们可以看到“正面的背面”,他是没有内容的,因此需要设置我们自己背面的背景色来覆盖掉,并写入文本。这里需要注意的是,我们的背面也需要再绕Y轴旋转一次,不然看来的内容仍是相反的。
那么如何让翻转效果看起来更协调呢,这里我的想法是,控制背面的背景色与封面保持一致,通过设置 setTimeout
函数让背面的内容晚点出来,以造成是我翻转卡片到某个角度后才能看见背面的文字。至于延时多久呢,这就慢慢调了哈哈。
.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;
}
翻转动画我设置的1s,延时用了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会出现图片大小变化div外层不变
}
// 没有被hover的卡片变模糊
.blur {
filter: blur(25px);
transform: scale(.6);
}
// 卡片点击翻转
.turned {
box-shadow: 0px 0px 20px 10px #f1c40f;
transform: perspective(900px) rotateY(180deg) scale(1) translateY(-50%);
}
// hover卡片放大,游戏结束后失效
.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;
}
// 游戏结束,未翻开的牌自动翻开向下移动
.gameOver {
transform: perspective(900px) rotateY(180deg) scale(1) translateY(50%);
cursor: default;
}
}
}
</style>
来源:https://juejin.cn/post/7062624081618665480
猜你喜欢
- 本文实例讲述了C#实现按数据库邮件列表发送邮件的方法。分享给大家供大家参考。具体实现方法如下:using System;using Syst
- 为什么需要对参数进行编码?相信有过开发的经验的广大程序员都知道,在Web中,若是直接在Url地址上传递参数值,若是中文,或者+等什么的就会出
- 问题引入作为一名Golang开发者,线上环境遇到过好几次连接数暴增问题(mysql/redis/kafka等)。纠其原因,Golang作为常
- 很久没有跟其他人做重构思想方面的交流了,可能大家都觉得不太好意思讨论,特别是“分离”的思想这么基础的话题,拿出来说怕会被“笑话”。做为页面重
- <!--#include file="admin_Checkuser.asp"--> <%
- 1、for循环写法基本和其他语言一致,只是没有了while循环,用for代替while。样例代码如下// for循环func loop1()
- 前言本文主要给大家介绍的关于Python批量压缩png的相关资料,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍:1.需求为什
- 在找工作的时候,我们会选择上网查询招聘的信息,或者是通过一些招聘会进行现场面试。但由于信息更新不及时,有一些岗位会出现下架的情况,如果我们不
- 一、python的基础语法1.行连接的方法是最后加上一个‘\'2.注释:多行注释三引号,#行注释;三引号定义的字符串原样输出(保存原
- 简介在日常的Python开发中,处理时间和日期的需求是非常常见的。尽管Python内置了 datetime 和 time 模块,但在某些情况
- SQL Server 提供系统数据类型集,定义了可与 SQL Server 一起使用的所有数据类型。下面列出系统提供的数据类型集。 可以定义
- 函数执行流程def foo1(b,b1=3): print("foo1 called",b,b1)def
- selenium主要是用来做自动化测试,支持多种浏览器,爬虫中主要用来解决JavaScript渲染问题。模拟浏览器进行网页加载,当reque
- 本文是将yolo3目标检测框架训练出来的ckpt文件固化成pb文件,主要利用了GitHub上的该项目。为什么要最终生成pb文件呢?简单来说就
- 一、前言现在盗图是非常常见的事情,许多人在使用图片时都不会标注图片的出处或者提及作者,这个时候水印就是个很好的东西了。我们可以给图片添加水印
- python用terminal输入参数import argparseif __name__ == '__main__':pa
- 本文实例讲述了Python可变和不可变、类的私有属性。分享给大家供大家参考,具体如下:可变和不可变items = []print(id(li
- 在开发测试平台的时候,虽然对某些关键功能做了权限设置,但毕竟是公司多人使用,有些数据的配置可能不小心被他人修改但未告知其他使用者,造成了诸多
- 在了解了JavaScript1.7的相关更新后,我们再继续关注JavaScript1.8的新特性。在W3C Group带来的JavaScri
- 一、复制原理主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新.当一个从服务器连接主