前言无缝轮播一直是面试的热门话题,大部分的回答都是复制第一个到最后一个。诚然,这种方法很标准,那么有没有替代方法呢?第一种方法是把所有的图一张一张的排列好,然后慢慢的移动,但是能不能只移动而不放置呢?如果你用过vue的transition,我们可以通过给每张图片加上进入动画和退出动画来模拟这个动作。进入动画是从最右边到屏幕中央。退出动画从屏幕中心向左。像这样移出的效果就是图片从右移到左,但是不同的是我们每个元素都有这个进入动画和退出动画,我们不需要关心是哪个元素,你只是旋转木马。不用vue怎么办?很简单,自己实现一个转场效果就可以了。主要是在显示下面两个元素的时候,也就是display属性不是none的时候,xx-enter-active动画元素消失的时候,先添加动画xx-leave-active,注意让动画在播放结束前消失animationend',animationEvent)}functionanimationEvent(e){e.target.className=e.target.className.replace('slide-leave-active','')e.target.style.display='none'e.target.removeEventListener('animationend',animationEvent)}functionshow(el){el.style.display='flex'el.className+='slide-enter-active'}这里我们使用Animationend来监听结束动画。注意这里每次添加新的类都需要重新添加监听器,否则无法监听。如果你不使用这个方法,你可以使用一个定时器来移除leave-active类。functionhide(el){el.className=el.className.replace('slide-enter-active','')el.className+='slide-leave-active'setTimeout(()=>{//结束animation清空类后el.className=el.className.replace('slide-leave-active','')el.style.display='none'},ANIMATION_TIME)//这个ANIMATION_TIME就是你动画执行的时间incss}那么,动画怎么写呢?.slide-enter-active{位置:绝对;动画:slideInease.5sforwards;}.slide-leave-active{位置:绝对;动画:slideOut向前缓动.5s;}@keyframesslideIn{0%{transform:translateX(100%);}100%{转换:translateX(0);}}@keyframesslideOut{0%{变换:translateX(0);}100%{转换:translateX(-100%);}}注意这里是forwards属性。这个属性意味着你的元素的状态将保持在动画结束后的状态。如果未设置,动画将运行一次。你的元素本来执行的是离开动画,执行完会回到中心位置。这时候你会问,上面的代码不是写的,执行完动画之后元素就隐藏了吗?如果你用上面的setTimeout命令元素执行完动画后消失,可能会出现瞬间的闪烁,因为在实际业务中,你的代码可能比较复杂,setTimeout不可能在这么精确的时间内执行。为了保险起见,让元素保持动画离开的最终状态,即translateX(-100%)。此时,元素已经在屏幕外了,所以不用担心它的性能。轮播逻辑怎么写?这很简单。当我们进入一个新元素时,我们可以同时移除旧元素,两者同时执行进入和退出动画。functionautoPlay(){setTimeout(()=>{toggleShow(newelement,oldelement)this.autoPlay()},DURATION)//DURATION为动画间隔时间}functiontoggleShow(newE,oldE){//oldeleandnewele同步动画hide(oldE)show(newE)}完整代码简单无缝轮播
