问题表现
使用的是swiper/react
组件想要实现的效果是匀速轮播,hover立刻停止,hover离开之后立马运动;但是如果只是使用swiperRef.current.swiper.autoplay.stop();
并没有立刻停止,这是因为swiper
的autopaly.stop()
方法只是暂停下一次的切换,而本次的切换还是要进行完,因此会有一个看起来延迟的效果;
代码如下:
const swiperConfig = {
initialSlide: -2,
direction: 'horizontal',
slidesPerView: 12,
loop: true,
speed: 6000,
dir: 'ltr', // 默认从右往左运行,‘rtl’ 从左往右运动
centeredSlides: true,
spaceBetween,
autoplay: {
delay: 0,
disableOnInteraction: false, // 用户操作后是否停止自动播放,默认为true,设为false则不会停止
pauseOnMouseEnter: true // 开启此功能,鼠标置于swiper时暂停自动切换,鼠标离开时恢复自动切换。
}
};
const handleMouseenter = () => {
if (swiperRef.current && swiperRef.current.swiper.autoplay) {
swiperRef.current.swiper.autoplay.stop();
}
};
const handleMouseleave = () => {
if (swiperRef.current && swiperRef.current.swiper.autoplay) {
swiperRef.current.swiper.autoplay.start();
}
};
<Swiper {...swiperConfig} ref={swiperRef}>
...
</Swiper>
// 这里使用 handleMouseenter和handleMouseleave方法表现情况和直接使用pauseOnMouseEnter属性是一样的,hover轮播的时候不会立刻停止,hover离开的时候会立刻运动
实现运动运动还需要重置一下css样式
.swiper-wrapper {
-webkit-transition-timing-function: linear; /*之前是ease-out*/
-moz-transition-timing-function: linear;
-ms-transition-timing-function: linear;
-o-transition-timing-function: linear;
transition-timing-function: linear;
}
问题解决历程
首先了解到上面的点之后的改进代码 (应该还不是百分之百解决,swiperslide之间还有marginLeft间距问题,可能会影响鼠标hover那个slide的运动速度与原slide有一点不同,细节自己再斟酌一下)
const handleMouseenter = () => {
// 存放鼠标悬浮时的transform属性(行内属性)
let nextTransForm = '';
// 轮播图从暂停位置移动到原本应到的位置所用的时间
let nextTime = 0;
if (swiperRef.current && swiperRef.current.swiper.autoplay) {
const swiperDom = swiperRef.current.swiper.el.children[0];
// 轮播图原本应移动到的位置
nextTransForm = swiperDom.style.transform;
let nextTransPosition = parseInt(swiperDom.style.transform.split('translate3d(')[1].split('px')[0], 10);
// 鼠标悬浮时时轮播图位置
const nowTransPosition = swiperRef.current.swiper.getTranslate();
// 计算轮播图从暂停位置移动到原本应到的位置所用的时间
const swiperSlideWidth = swiperDom.children[0].getBoundingClientRect().width;
nextTime = 6000 * (Math.abs(Math.abs(nextTransPosition) - Math.abs(nowTransPosition)) / swiperSlideWidth);
setSwiperData({nextTransForm, nextTime});
const instance = swiperRef.current.swiper.getTranslate();
swiperRef.current.swiper.setTranslate(instance);
swiperRef.current.swiper.autoplay.stop();
}
};
const handleMouseleave = () => {
const {nextTransForm, nextTime} = swiperData;
if (swiperRef.current && swiperRef.current.swiper.autoplay) {
const swiperDom = swiperRef.current.swiper.el.children[0];
swiperDom.style.transform = nextTransForm;
swiperDom.style.transitionDuration = nextTime + 'ms';
swiperRef.current.swiper.autoplay.start();
}
};