如何快速实现一个无缝轮播效果

简介: 【8月更文挑战第24天】如何快速实现一个无缝轮播效果

需求简介

轮播图是我们前端开发中的一个常见需求,在项目开发中,我们可以使用element、ant等UI库实现。某些场景,为了一个简单的功能安装一个库是没必要的,我们最好的选择就是手搓。
我们来看一个需求
image.png
上述需求核心就是实现一个无缝轮播的切换效果。以这个需求为例,我们看看最终实现效果:
240329 225619.gif

实现思路

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

const list = ref([
    {
   
    name: 1, id: 1 }, 
    {
   
    name: 2, id: 2 },
    {
   
    name: 3, id: 3 }
])

如果我们想无缝切换的展示这个数据,最简单的代码就是动态的改变下面的代码的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能够重新渲染,触发元素离开和进入的样式。

至此,我们就完成了基本功能样式
240329 225619.gif

轮播的停止与恢复

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

<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;
}

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

相关文章
|
存储 人工智能 OLAP
LangChain+通义千问+AnalyticDB向量引擎保姆级教程
本文以构建AIGC落地应用ChatBot和构建AI Agent为例,从代码级别详细分享AI框架LangChain、阿里云通义大模型和AnalyticDB向量引擎的开发经验和最佳实践,给大家快速落地AIGC应用提供参考。
133582 94
|
7月前
|
存储 人工智能 前端开发
从零到一构建PACS:如何设计一套能处理海量影像的企业级后端系统
开发医院PACS系统是跨医学影像标准(DICOM/HL7/IHE)、分布式架构、高性能前后端、海量存储与AI集成的复杂工程,需兼顾合规性、稳定性与临床体验。
598 1
Echarts实战案例代码(8):设置itemStyle渐变color属性实现柱图的伪3D效果的解决方案
Echarts实战案例代码(8):设置itemStyle渐变color属性实现柱图的伪3D效果的解决方案
737 0
|
9月前
|
人工智能 搜索推荐 持续交付
阿里云GPU服务器租用价格表2026年最新:L20/A10/V100/T4/P100/P4 GPU卡支持
阿里云2026年最新GPU服务器(现称EGS弹性GPU服务)支持L20、A10、V100等多款GPU卡,覆盖AI推理、图形渲染、科学计算等场景。提供按量、包月、包年多种计费,gn8is(L20)等实例月付低至6919元起,支持1小时起租与机密计算。(239字)
11047 9
|
JavaScript API C++
TypeScript 核心概念:`type` vs `interface`,如何明智选择?
TypeScript 核心概念:`type` vs `interface`,如何明智选择?
710 133
|
7月前
|
存储 Java BI
SpringBoot门诊系统源码,Java门诊系统源码,高可用、高并发架构
挂号预约的管理内容主要包括:患者身份登记、挂号处理、门诊安排、号表生成、预约通知等,提供患者信息的查询和有关挂号工作的统计功能
311 2
SpringBoot门诊系统源码,Java门诊系统源码,高可用、高并发架构
|
JavaScript UED 开发者
精彩!Vue 实现消息列表向上无缝滚动!丝滑...
精彩!Vue 实现消息列表向上无缝滚动!丝滑...
|
存储 前端开发 索引
React 图片轮播组件 Image Carousel
本文介绍了如何使用React创建图片轮播组件。首先,解释了图片轮播的基本概念和组件结构,包括图片容器、导航按钮、指示器和自动播放功能。接着,通过代码示例详细说明了创建基本组件、添加自动播放、处理边界情况的步骤。还探讨了常见问题如状态更新不及时、内存泄漏和样式问题,并提供了解决方案。最后,介绍了进阶优化,如添加过渡效果、支持触摸事件和动态加载图片,帮助读者构建更完善的轮播组件。
561 16
|
设计模式 消息中间件 供应链
前端必须掌握的设计模式——发布订阅模式
发布订阅模式(Publish-Subscribe Pattern)是一种设计模式,类似于观察者模式,但通过引入第三方中介实现发布者和订阅者的解耦。发布者不再直接通知订阅者,而是将消息发送给中介,由中介负责分发给订阅者。这种方式提高了异步支持和安全性,适合复杂、高并发场景,如消息队列和流处理系统。代码实现中,通过定义发布者、订阅者和中介接口,确保消息的正确传递。此模式在前端开发中广泛应用,例如Vue的数据双向绑定。
|
移动开发 JavaScript HTML5
Vue3视频播放(Video)
这篇文章介绍了如何在Vue 3框架中创建一个视频播放组件(Video),支持自定义视频源、封面、自动播放等多种播放选项和样式设置。
3596 1
Vue3视频播放(Video)