js使用transition效果实现无缝滚动
前言
无缝轮播一直是面试的热门题目,而大部分答案都是复制第一张到最后。诚然,这种方法是非常标准,那么有没有另类一点的方法呢?
第一种方法是需要把所有图片一张张摆好,然后慢慢移动的,
但是我能不能直接不摆就硬移动呢?
如果你使用过 vue 的transition
,我们是可以通过给每一张图片来添加入场动画和离场动画来模拟这个移动
- 进场动画就是从最右侧到屏幕中央
- 出场动画是从屏幕中央到左侧移出
这样看起来的效果就是图片从右边一直往左移动,但是这个不一样的地方是,我们每一个元素都有这个进场动画和离场动画,我们根本不用关心它是第几个元素,你只管轮播就是。
如果不用 vue 呢?
很简单,我们自己实现一个transtition
的效果就好啦,主要做的是以下两点
- 元素显示的时候,即 display 属性不为 none 的时候,添加
xx-enter-active
动画 - 元素消失的时候,先添加动画
xx-leave-active
, 注意要让动画播完才消失
function hide(el){ el.className = el.className.replace(' slide-enter-active','') el.className += ' slide-leave-active' el.addEventListener('animationend',animationEvent) } function animationEvent(e){ e.target.className = e.target.className.replace(' slide-leave-active','') e.target.style.display = 'none' e.target.removeEventListener('animationend',animationEvent) } function show(el){ el.style.display = 'flex' el.className += ' slide-enter-active' }
这里我们使用了animationend
来监听动画结束,注意这里每次从新添加类的时候需要重新添加监听器,不然会无法监听。如果不使用这个方法你可以使用定时器的方式来移除 leave-active 类。
function hide(el){ el.className = el.className.replace(' slide-enter-active','') el.className += ' slide-leave-active' setTimeout(()=>{ //动画结束后清除 class el.className = el.className.replace(' slide-leave-active','') el.style.display = 'none' }, ANIMATION_TIME) //这个 ANIMATION_TIME 为你在 css 中动画执行的时间 }
那么,动画怎么写呢?
.slide-enter-active{ position: absolute; animation: slideIn ease .5s forwards; } .slide-leave-active{ position: absolute; animation: slideOut ease .5s forwards; } @keyframes slideIn { 0%{ transform: translateX(100%); } 100%{ transform: translateX(0); } } @keyframes slideOut { 0%{ transform: translateX(0); } 100%{ transform: translateX(-100%); } }
需要注意的是这里的 forwards
属性,这个属性表示你的元素状态将保持动画后的状态,如果不设置的话,动画跑完一遍,你的元素本来执行了离开动画,执行完以后会回来中央位置杵着。这个时候你会问了,上面的代码不是写了,动画执行完就隐藏元素吗?
如果你使用上面的 setTimeout 来命令元素执行完动画后消失,那么可能会有一瞬间的闪烁,因为实际业务中,你的代码可能比较复杂,setTimeout 没法在那么精准的时间内执行。保险起见,就让元素保持动画离开的最后状态,即translateX(-100%)
。此时元素已经在屏幕外了,不用关心它的表现了
轮播逻辑怎么写?
很简单,我们进一个新元素的时候同时移除旧元素即可,两者同时执行进场和离场动画即可。
function autoPlay(){ setTimeout(()=>{ toggleShow(新元素, 旧元素) this.autoPlay() },DURATION) //DURATION 为动画间隔时间 } function toggleShow(newE,oldE){ //旧 ele 和新 ele 同时动画 hide(oldE) show(newE) }
完整代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>swiper</title> <style> .container{ position: relative; overflow: hidden; height: 300px; overflow: hidden; } .item{ width: 100%; font-size: 36px; height: 100%; display: flex; justify-content: center; align-items: center; } .item:nth-child(2n+1){ background-color: gray; } .item:nth-child(2n){ background-color: pink; } .slide-enter-active{ position: absolute; animation: slideIn ease .5s forwards; } .slide-leave-active{ position: absolute; animation: slideOut ease .5s forwards; } @keyframes slideIn { 0%{ transform: translateX(100%); } 100%{ transform: translateX(0); } } @keyframes slideOut { 0%{ transform: translateX(0); } 100%{ transform: translateX(-100%); } } </style> </head> <body> <div class="container"> <div class="item" style="display:flex" >1</div> <div class="item" style="display:none" >2</div> <div class="item" style="display:none" >3</div> <div class="item" style="display:none" >4</div> </div> </body> <script> const DURATION = 3000 let list = document.querySelectorAll('.item') let curIndex = 0 autoPlay() function autoPlay(){ setTimeout(()=>{ toggleShow(list[(curIndex+1)%list.length], list[curIndex]) curIndex = (curIndex+1)%list.length this.autoPlay() },DURATION) } function toggleShow(newE,oldE){ //旧 ele 和新 ele 同时动画 hide(oldE) show(newE) } //离场 function hide(el){ el.className = el.className.replace(' slide-enter-active','') // 注意这里前面有个空格 el.className += ' slide-leave-active' el.addEventListener('animationend',animationEvent) } function animationEvent(e){ e.target.className = e.target.className.replace(' slide-leave-active','') e.target.style.display = 'none' e.target.removeEventListener('animationend',animationEvent) } //进场 function show(el){ el.style.display = 'flex' el.className += ' slide-enter-active' } </script> </html>
作者:李大雷 原文链接:点击这里
码云笔记 » js使用transition效果实现无缝滚动