在标准配置下,Swiper组件呈现出的基本轮播效果是逐个轮播,而非连续平滑滚动的走马灯效果。 若要实现平滑滚动,且可手动切换,需要对Swiper进行一些定制化调整,包括但不限于:
- 选择合适的插件
- 监听切换事件
- 修改动画效果
Swiper基础使用
swiper提供了vue的版本,官网在这:swiperjs.com/vue
Swiper Vue.js 插件作为 Swiper 主库的一部分,仅通过 NPM 提供:
npm i swiper
通过 swiper/vue 中引入两个组件 Swiper 和 SwiperSlide:
<script setup>
import { Swiper, SwiperSlide } from 'swiper/vue'
import 'swiper/css'
</script>
<template>
<Swiper>
<SwiperSlide v-for="item in 8" :key="item" class="bg-blueGray">
<div class="h-300px">
Slide {{ item }}
</div>
</SwiperSlide>
</Swiper>
</template>
这样就实现了一个最基础的手动切换轮播图
参数
可以设置一些参数来满足定制化的需求,如:
- slidesPerView:默认可见的slide数量,可以指定某个具体的数字或者'auto'
- spaceBetween:slide的边距,单位是px。
- speed:slide之间的过渡时间(毫秒)
可在官网查看所有支持的参数,某些参数需要引入对应的modules,如autoplay,free-mode等
<Swiper
:slides-per-view="4"
:space-between="20"
:speed="2000"
>
...
</Swiper>
加了以上参数以后,swiper的效果,划动切换以后的时间将持续2秒
方法
自动滚动
swiper/vue 的自动滚动,直接加 autoplay 是没用的,需要从 swiper/modules 引入 Autoplay ,官网指路
<script setup>
import { Swiper, SwiperSlide } from 'swiper/vue'
import { Autoplay } from 'swiper/modules'
import 'swiper/css'
</script>
<template>
<Swiper
:slides-per-view="4"
:space-between="20"
:speed="2000"
:modules="modules"
autoplay
loop
>
<SwiperSlide v-for="item in 8" :key="item" class="bg-black">
<div class="h-300px c-white">
Slide {{ item }}
</div>
</SwiperSlide>
</Swiper>
</template>
autoplay 也是可以作为一个对象,单独设置一些属性的,如:
- delay:多少秒切换一次
- pauseOnMouseEnter:设置为true的话,在自动播放的情况下,鼠标移入会停止动画
- reverseDirection:设置为true的话,反向滚动
- stopOnLastSlide:设置为true的话,停在最后一个slide
获取swiper实例
正常情况下,在vue中,是通过给dom节点设置ref属性,来获取dom实例,但是swiper的方法并不在通过ref获取的实例中,要获取swiper真正的实例,需要监听swiper方法获取,可以输出对比一下
<script setup>
import { Swiper, SwiperSlide } from 'swiper/vue'
import 'swiper/css'
const swiperInstance = ref(null)
function onSwiper(swiper) {
console.log(swiper, swiperInstance.value)
}
</script>
<template>
<Swiper
ref="swiperInstance"
@swiper="onSwiper"
...
>
...
</Swiper>
</template>
自定义切换
获取了swiper实例以后,就能通过它调用swiper对应的方法了,如这里需要定制的手动切换,全部的方法可在官网查看。
切换的方法,如果对定制要求不是很高,可以直接引入 pagination 的moudule。
这里实现的是自定义了两个切换按钮,当切换时,需要停止当前的自动播放动画,然后做一些边界值的变化,这里不直接使用swiper.slideNext,swiper.slidePrev的原因是,这样切换的时候swiper还是要等当前silde结束自动切换以后,再切换到下一张,不是立马切换的效果,所以这里使用 swiper.slideToLoop 达到一个立即切换的效果。
<script setup>
import { Swiper, SwiperSlide } from 'swiper/vue'
import { Autoplay } from 'swiper/modules'
import 'swiper/css'
const modules = [Autoplay]
const swiperInstance = ref(null)
function onSwiper(swiper) {
swiperInstance.value = swiper
}
let autoplayTimer = null
function handleNext(type) {
const swiper = swiperInstance.value
swiper.autoplay.stop()
if (type === 'prev') {
swiper.slideToLoop(swiper.realIndex <= 1 ? 7 : swiper.realIndex - 1, 500)
}
else {
swiper.slideToLoop(swiper.realIndex >= 7 ? 0 : swiper.realIndex + 1, 500)
}
clearInterval(autoplayTimer)
autoplayTimer = setTimeout(() => {
swiper.autoplay.start()
}, 2000)
}
</script>
<template>
<div>
<Swiper
:slides-per-view="4"
:space-between="20"
:speed="1000"
:modules="modules"
loop
:autoplay="{ delay: 500 }"
@swiper="onSwiper"
>
<SwiperSlide v-for="item in 8" :key="item" class="bg-blueGray">
<div class="h-300px">
Slide {{ item }}
</div>
</SwiperSlide>
</Swiper>
<el-button @click="handleNext('prev')">
<div class="i-ms-chevron-left" />
</el-button>
<el-button @click="handleNext('next')">
<div class="i-ms-chevron-right" />
</el-button>
</div>
</template>
平滑滚动
最后要达到平滑滚动的效果,需要引入一个 free-mode 的module,因为是平滑,所以 autoplay.delay 就需要设置为0了,最后一步就是修改swiper的动画效果,以下是完整代码,效果就是文章开头的效果
<script setup>
import { Swiper, SwiperSlide } from 'swiper/vue'
import { Autoplay, FreeMode } from 'swiper/modules'
import 'swiper/css'
import 'swiper/css/free-mode'
const modules = [Autoplay, FreeMode]
const swiperInstance = ref(null)
function onSwiper(swiper) {
swiperInstance.value = swiper
}
let autoplayTimer = null
function handleNext(type) {
const swiper = swiperInstance.value
swiper.autoplay.stop()
if (type === 'prev') {
swiper.slideToLoop(swiper.realIndex <= 1 ? 7 : swiper.realIndex - 1, 500)
}
else {
swiper.slideToLoop(swiper.realIndex >= 7 ? 0 : swiper.realIndex + 1, 500)
}
clearInterval(autoplayTimer)
autoplayTimer = setTimeout(() => {
swiper.autoplay.start()
}, 2000)
}
</script>
<template>
<div>
<Swiper
:slides-per-view="4"
:space-between="20"
:speed="1000"
:modules="modules"
:autoplay="{ delay: 0 }"
loop
@swiper="onSwiper"
>
<SwiperSlide v-for="item in 8" :key="item" class="bg-blueGray">
<div class="h-300px">
Slide {{ item }}
</div>
</SwiperSlide>
</Swiper>
<el-button @click="handleNext('prev')">
<div class="i-ms-chevron-left" />
</el-button>
<el-button @click="handleNext('next')">
<div class="i-ms-chevron-right" />
</el-button>
</div>
</template>
<style>
.swiper-free-mode .swiper-wrapper {
transition-timing-function: linear;
}
</style>