需求

  1. 组件的平滑的滚动
  2. 鼠标放置后立即在当前位置停止

基础设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SwiperOptions: {
// basic
width: window.innerWidth,
resistanceRatio: 0,
speed: 3000,
observer: true,
observeParents: true,
slidesPerGroup: 1,
// autoplay
autoplay: {
delay: 0, // 每个图片移动完成后间隔
disableOnInteraction: false // 触摸后是否停止自动移动
},
freeMode: true, // 不贴合
// loop
loop: true, // 循环
loopedSlides: this.data.length,
loopAdditionalSlides: this.data.length,
// grid
centeredSlides: true,
slidesPerView: 'auto',
spaceBetween: 25
}

问题一

Swiper中有autoplay(自动播放)和freeMode(slide会根据惯性滑动可能不止一格且不会贴合),但是自动播放时,每个slide会有加速减速的停顿

解决方案

覆盖Swiper4自带的CSS过度效果

1
2
3
4
5
6
7
8
9
10
11
<style lang="stylus">
// 使图片预览可以平滑滚动,这里不能使用scoped,否则不能覆盖组件外的CSS
.image-swiper-wrapper // 外层div的class
.swiper-container-free-mode > .swiper-wrapper
-webkit-transition-timing-function linear !important
-moz-transition-timing-function linear !important
-ms-transition-timing-function linear !important
-o-transition-timing-function linear !important
transition-timing-function linear !important
margin 0 auto !important
</style>

问题二

可以鼠标悬停时使用Swiper提供的this.swiper.autoplay.stop()停止播放,但是调用这个API后仍然需要等待最近一张的图片移动完成

解决方案

使用JS自定义位移来停止/播放Swiper

1
2
3
4
5
6
7
8
9
10
11
12
13
stop () {
// this.swiper.translate为过度结束的位移,this.swiper.getTranslate()为当前实时的位移,this.slideWidth为slide的宽度px
// 计算之后平滑移动到this.swiper.translate需要的速度,并储存下来
this.lastNeedSwiperSpeed = Math.abs(Math.abs(this.swiper.getTranslate()) - Math.abs(this.swiper.translate)) / (this.slideWidth + this.swiper.params.spaceBetween) * this.swiper.params.speed
// setTranslate到当前位置,并停止autoplay
this.swiper.setTranslate(this.swiper.getTranslate())
this.swiper.autoplay.stop()
},
start () {
// 使用刚才计算出的速度,移动到当前slide,即将当前slide的移动到头部的动画完成,开启autoplay
this.swiper.slideTo(this.swiper.activeIndex, this.lastNeedSwiperSpeed)
this.swiper.autoplay.start()
}