【大前端vue:组件】鼠标上移 出现动画
<template>
<div class="view-introduction-culture">
<div class="culture-wrapper">
<h2 class="culture-title">鼠标上移:展示动画 显示出来</h2>
<div class="culture-content">
<div v-for="(item, index) in cultureList" :key="index" class="culture-item"
@mouseenter="handleMouseEnter(index)" @mouseleave="handleMouseLeave(index)">
<!-- 背景图片层 -->
<div class="item-bg" :style="{ backgroundImage: `url(${item.bgImage})` }">
<div class="item-number">{{ item.number }}</div>
<div class="item-name">{{ item.name }}</div>
<div class="item-icon">
<img :src="item.icon" :alt="item.name">
</div>
</div>
<!-- 悬浮展示层 -->
<div class="hover-content" :class="{ active: activeIndex === index }">
<div class="hover-text">{{ item.description }}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'CultureIndex',
data() {
return {
activeIndex: null, // 当前激活的索引
hoverTimer: null, // 用于存储定时器
cultureList: [
{
number: '01',
name: '标签1',
icon: '/icons/culture-1.png',
bgImage: '/images/culture-bg-1.jpg',
description: '标签描述文字'
},
{
number: '02',
name: '标签2',
icon: '/icons/culture-2.png',
bgImage: '/images/culture-bg-2.jpg',
description: '标签描述文字'
},
{
number: '03',
name: '标签3',
icon: '/icons/culture-3.png',
bgImage: '/images/culture-bg-3.jpg',
description: '标签描述文字'
},
{
number: '04',
name: '标签4',
icon: '/icons/culture-4.png',
bgImage: '/images/culture-bg-4.jpg',
description: '标签4描述文字'
}
]
}
},
methods: {
handleMouseEnter(index) {
// 清除之前的定时器
if (this.hoverTimer) {
clearTimeout(this.hoverTimer)
}
// 设置新的定时器
this.hoverTimer = setTimeout(() => {
this.activeIndex = index
}, 300)
},
handleMouseLeave(index) {
// 清除定时器
if (this.hoverTimer) {
clearTimeout(this.hoverTimer)
this.hoverTimer = null
}
// 只有当前激活的项目是当前离开的项目时,才清除激活状态
if (this.activeIndex === index) {
this.activeIndex = null
}
}
},
// 组件销毁时清理定时器
beforeDestroy() {
if (this.hoverTimer) {
clearTimeout(this.hoverTimer)
}
}
}
</script>
<style lang="scss">.view-introduction-culture {
width: 100%;
background: {
image: url('@/assets/image/introduction/bg.png') no-repeat center center;
size: 100% 100%;
color: #F1F6FF;
}
padding: 70px 0;
.culture-wrapper {
width: 1200px;
margin: 0 auto;
}
.culture-title {
text-align: center;
font-size: 28px;
color: #333;
margin-bottom: 51px;
}
.culture-content {
display: flex;
justify-content: space-between;
}
.culture-item {
position: relative;
width: 302px;
height: 300px;
overflow: hidden;
cursor: pointer;
.item-bg {
width: 100%;
height: 100%;
background: {
size: cover;
position: center;
}
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #fff;
padding: 20px;
&::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.6));
}
}
.item-number,
.item-name,
.item-icon {
position: relative;
z-index: 1;
}
.item-number {
font-size: 36px;
font-weight: bold;
margin-bottom: 10px;
}
.item-name {
font-size: 24px;
margin: 10px 0;
}
.item-icon {
margin-top: 20px;
img {
width: 40px;
height: 40px;
}
}
.hover-content {
position: absolute;
top: 0;
left: 0;
width: 302px;
height: 500px;
background: pink;
opacity: 0;
display: flex;
align-items: center;
justify-content: center;
transition: opacity 0.1s ease;
padding: 30px;
pointer-events: none; // 防止悬浮层影响鼠标事件
&.active {
opacity: 0.8;
}
.hover-text {
color: #fff;
font-size: 16px;
line-height: 1.8;
text-align: center;
}
}
}
}
</style>
</style>