稀土掘金技术社区 01月12日
如何快速实现一个无缝轮播效果
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文详细介绍了如何使用纯前端技术实现一个无缝轮播图组件,避免了引入额外的UI库。文章从核心思路出发,通过动态改变显示的列表索引,配合Vue的Transition组件实现动画效果。详细讲解了如何设置定时器进行自动轮播,以及如何通过鼠标悬停控制轮播的暂停与恢复。同时,还提供了解决页面切换时可能出现的重影问题的方案。最终实现了一个功能完整、样式流畅的无缝轮播图,为前端开发者提供了实用的技术参考。

🔄核心思路:通过动态改变显示的列表索引实现轮播,而非直接操作DOM。使用`v-show`控制卡片的显示与隐藏,配合定时器自动切换索引。

✨动画效果:利用Vue的`Transition`组件,为卡片切换添加过渡动画效果。通过设置`.v-enter-from`、`.v-enter-to`、`.v-leave-from`和`.v-leave-to`等CSS类,控制卡片进入和离开时的动画,实现流畅的切换效果。

🖱️ 交互控制:通过监听鼠标的`mouseenter`和`mouseleave`事件,实现鼠标悬停时停止轮播,移开时恢复轮播的功能。使用`clearInterval`和`setInterval`控制定时器的启停。

👁️‍🗨️ 解决重影:通过监听`visibilitychange`事件,在页面切换到后台时停止轮播,切换回前台时恢复轮播,解决因页面长时间处于后台而导致的重影问题。

原创 石小石Orz 2025-01-10 08:30 重庆

点击关注公众号,“技术干货”及时达!

点击关注公众号,“技术干货” 及时达!

需求简介

「轮播图」是我们前端开发中的一个常见需求,在项目开发中,我们可以使用element、ant等UI库实现。某些场景,为了一个简单的功能安装一个库是没必要的,我们最好的选择就是手搓。

我们来看一个需求

上述需求核心就是实现一个无缝轮播的切换效果。以这个需求为例,我们看看最终实现效果:

实现思路

要想实现一个「无缝的轮播效果」,其实非常简单,核心思想就是「动态改变显示的列表」而已。比如我们有这样一个数组

const list = ref([
    { name1id1 }, 
    { name2id2 },
    { name3id3 }
])

如果我们想无缝切换的展示这个数据,最简单的代码就是动态的改变下面的代码的index

<template>
    <div>
       {{ list[index] }}
    </div>

</template>
<script setup>
    const index = ref(0)
    const list = ref([{ name: 1, id: 1 }, { name: 2, id: 2 }, { name: 2, id: 2 }])
<scriptp>

那如何实现切换的样式呢?也非常简单,我们只要给元素添加一个出现样式和离开样式即可。现在,我们来具体实现这样一个需求。

技术方案

数据的动态切换

要想实现一个数据的动态循环切换效果,是非常容易的:

<template>
 <div v-for="(build, index) in list" :key="index">
    <div v-show="index === selectIndex">
       卡片自定义内容
    </div>
 </div>

</template>
<script setup>
const selectIndex = ref(0)
const list = ref(
    [{ name: "卡片1", id: 1 }, { name: "卡片1", id: 2 }, { name: "卡片1", id: 2 }]
)
/
/ #计时器实例
let timer: any = null
/
/ >计时器逻辑
const timeFuc = () => {
    timer = setInterval(() => {
      /
/ 更改选中的index
      if (selectIndex.value >= list.value.length - 1) {
        selectIndex.value = 0
      } else {
        selectIndex.value++
      }
    }, 5000)
}
timeFuc()
<scriptp>

上述代码中,我们设置了一个定时器,定时器每5s执行一次,每次执行都会动态更改当前要显示的数据索引值,当索引值达到最大实,在将其重置。通过上述的简单代码,我们就实现了一个可以自动切换的循环渲染的卡片。

动画添加

要想实现最终效果的动态效果也非常容易,我们只需要给每个元素出现时设置一些样式,离开时设置一些样式即可。借助vue的「Transition组件」,我们能很容易实现这样一个效果。

如果你不了解vue的Transition组件,请去官网补充下知识:https://cn.vuejs.org/guide/built-ins/transition.html

<template>
<div class="main-content">
    <Transition v-for="(build, index) in list" :key="selectIndex">
        <div class="banner-scroll-wrap" v-show="index === selectIndex">
            卡片自定义内容
        </div>
    </Transition>
</div>

</template>
<script setup>
const selectIndex = ref(0)
const list = ref(
    [{ name: "卡片1", id: 1 }, { name: "卡片1", id: 2 }, { name: "卡片1", id: 2 }]
)
/
/ #计时器实例
let timer: any = null
/
/ >计时器逻辑
const timeFuc = () => {
    timer = setInterval(() => {
      /
/ 更改选中的index
      if (selectIndex.value >= list.value.length - 1) {
        selectIndex.value = 0
      } else {
        selectIndex.value++
      }
    }, 5000)
}
timeFuc()
<scriptp>
<style lang="less" scoped>
.main-content {
    position: relative;
    height: 100%;
    .banner-scroll-wrap {
        position: absolute;
        top: 0;
        bottom: 0;
        right: 0;
        left: 0;
    }
}
.v-enter-from {
    transform: translateX(100%);
    opacity: 0;
}
.v-enter-active,
.v-leave-active {
    transition: transform 600ms ease-in-out, opacity 600ms ease-in-out;
}
.v-enter-to {
    transform: translateX(0);
    opacity: 1;
}
.v-leave-from {
    transform: translateX(0);
    opacity: 1;
}
.v-leave-to {
    transform: translateX(-100%);
    opacity: 0;
}
<style/
>

上述代码中,由于 selectIndex是动态的,元素不断地在显示与隐藏。因此,Transition标签的进入样式和离开样式会动态触发,从而形成切换效果。

v-enter是元素的进入样式,进入时,我们从最右边偏移100%的距离到正常位置,透明度从0到1,这个过程持续0.6s,实现了元素左移淡入的效果。

v-leave是元素的离开样式,离开时,我们从正常位置偏移到100%的左侧位置,透明度从1到0,这个过程持续0.6s,实现了元素左移淡出的效果。

在这些类的共同作用下,我们实现了元素的动态切换。

你可能注意到了我给元素设置了一个banner-scroll-wrap类名,并使用了position: absolute,这样设置的注意目的是保证切换离开元素的淡出效果和进入元素的淡入效果是连贯的。如果你不这样写,可能会出现样式问题。

此外,「注意我给Transition设置了key="Transition"」,这样些会保证每次数据在切换时,transition能够重新渲染,触发元素离开和进入的样式。

至此,我们就完成了基本功能样式

轮播的停止与恢复

很常见的一种情况就是我们需要鼠标放在卡片上时停止轮播,离开卡片的时候恢复轮播,这非常容易。

<template>
<div class="main-content"  @mouseenter="stop()" @mouseleave="start()">
    <Transition v-for="(build, index) in list" :key="selectIndex">
        <div class="banner-scroll-wrap" v-show="index === selectIndex">
            卡片自定义内容
        </div>
    </Transition>
</div>

</template>
<script setup>
const selectIndex = ref(0)
const list = ref(
    [{ name: "卡片1", id: 1 }, { name: "卡片1", id: 2 }, { name: "卡片1", id: 2 }]
)
/
/ #计时器实例
let timer: any = null
/
/ >计时器逻辑
const timeFuc = () => {
    timer = setInterval(() => {
      /
/ 更改选中的index
      if (selectIndex.value >= list.value.length - 1) {
        selectIndex.value = 0
      } else {
        selectIndex.value++
      }
    }, 5000)
}
  /
/ >开启轮播
  const start = () => {
    if (timer) return
    timeFuc()
  }
  /
/ >关闭轮播
  const stop = () => {
    clearInterval(timer)
    timer = null
  }
timeFuc()
<scriptp>
<style lang="less" scoped>
<style/
>

解决重影问题

在某些情况下,我们离开这个页面很久后(浏览器切换到其他选项卡),然后在切回来的时候,可能会出现短暂的画面重影问题,这个问题也很好解决,加上下面的代码即可

<script setup>
    //...
    // 解决切屏后重影的问题
  onMounted(() => {
    document.addEventListener('visibilitychange', () => {
      // 用户息屏、或者切到后台运行 (离开页面)
      if (document.visibilityState === 'hidden') {
        stop()
      }
      // 用户打开或回到页面
      if (document.visibilityState === 'visible') {
        start()
      }
    })
  })
    
  onBeforeUnmount(() => stop())
<scriptp>

visibilitychange 事件:当其选项卡的内容变得可见或被隐藏时,会在 document 上触发 visibilitychange 事件。该事件不可取消。

总结

在本教程中,我们通过简单代码实现了无缝轮播效果,样式是左右切换,我们也可以通过样式控制实现上下切换的效果,比如将translateX设置为translateY即可。

 .v-enter-from {
    transform: translateY(100%);
    opacity: 0;
}

时间原因,本教程也没有对技术上做深究,也希望各位大佬能提供自己的思路与建议,感谢大家分享!

点击关注公众号,“技术干货” 及时达!

阅读原文

跳转微信打开

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

轮播图 Vue Transition 前端开发 无缝轮播
相关文章