代码链接:我的GitHub
项目预览:预览
目的:通过CSS + jQuery的方式实现自动无缝轮播。
上一篇博文总结了使用jQuery实现轮播,虽然是自动轮播,但是这个轮播有个不足之处:
他会在轮播结束的时候往左跳,跳回轮播开始的地方,这样就显得轮播效果很突兀,过渡不自然。
怎么把他变成像下面这样的无缝轮播,轮播结束的时候继续往右跳,继续下一轮播放呢?:
思路:把所有的轮播图片划分为三种状态,分别是准备轮播进入(enter)、在轮播中(current)、轮播结束后离开(leave),一张图片先是准备轮播,然后进入轮播,接着离开轮播进入到准备轮播的状态,等待下一次播送。
1.HTML结构
<div class="window3">
<div class="images3">
<img src="./img/function-01.jpg" alt="" width=960 height=540>
<img src="./img/git-01.jpg" alt="" width=960 height=540 >
<img src="./img/JQUERY-01.jpg" alt="" width=960 height=540>
<img src="./img/内存-01.jpg" alt="" width=960 height=540>
<img src="./img/数组-01.jpg" alt="" width=960 height=540>
</div>
</div>
接着确定轮播图的样式:
2.CSS样式
-
确定轮播窗口尺寸和轮播图片的位置排列
在之前的博文中,我们的CSS使用的是
display:flex
搭配translateX()
来实现轮播功能,但是在这里,因为实现思路改变了,我们需要根据状态的不同把图片划分到不同的区域,所以使用了position:absolute
搭配translateX()
。.window3 { 960px; height: 540px; margin: 30px auto; overflow: hidden; border: 1px solid red; } .images3 { position: relative; } .images3 img { 100%; transition: all 0.5s; position: absolute; top: 0; }
-
给图片添加状态
根据图片的状态的不同,划分到不同的区域。.images3 img.current { left: 0; transform: translateX(0); z-index: 1; } .images3 img.leave { transform: translateX(-100%); z-index: 1; } .images3 img.enter { transform: translateX(100%) }
3.添加JS
添加js控制元素样式的变化。
-
先给每一张图片划分状态
$('.images3 img:nth-child(1)').addClass('current') $('.images3 img:nth-child(2)').addClass('enter') $('.images3 img:nth-child(3)').addClass('enter') $('.images3 img:nth-child(4)').addClass('enter') $('.images3 img:nth-child(5)').addClass('enter')
-
设定每两秒自动轮播
//设定开始轮播的图片x let m = 1 setInterval(() => { //加入判断,每当一轮轮播结束,都让轮播从第一张图片开始(重设x=1) if(m>5){ m = m % 5 if (m === 0){ m = 5 } } // 使用ES6插值法把n传进去 $(`.images3 img:nth-child(${m})`).removeClass('current').addClass('leave') //one()表示只此一次,transitonend表示动画结束时 .one('transitionend',(e) => { $(e.currentTarget).removeClass('leave').addClass('enter') }) $(`.images3 img:nth-child(${m+1})`).removeClass('enter').addClass('current') m += 1 },2000)
这样我们就完成了一个无缝轮播了!
4.优化代码
把功能重复的代码封装成一个函数,让代码更简洁。
$('.images3 img:nth-child(1)').addClass('current')
$('.images3 img:nth-child(2)').addClass('enter')
$('.images3 img:nth-child(3)').addClass('enter')
$('.images3 img:nth-child(4)').addClass('enter')
$('.images3 img:nth-child(5)').addClass('enter')
// 优化后
functiont imgsInit(){
let n = 1
$(`.images3 img:nth-child(${n})`).addClass('current')
.siblings().addClass('enter')
}
if(x>5){
x = x % 5
if (x === 0){
x = 5
}
}
// 优化过后:
function x(m){
if(m>5){
m = m % 5
if(m === 0){
m = 5
}
}
}
//这段代码的主要功能是对一个jQuery对象添加/删除样式
$(`.images3 img:nth-child(${x})`).removeClass('current').addClass('leave')
// 优化过后:
function makeLeave($node){
$node.removeClass('current').addClass('leave')
return $node
}
//其他的依次类推
function makeEnter($node){
$node.removeClass('leave').addClass('enter')
return $node
}
function makeCurrent($node){
$node.removeClass('enter').addClass('current')
return $node
}
我们的主要代码就变成了:
let m = 1
setInterval(() => {
makeLeave($(`.images3 img:nth-child(${x(m)})`))
.one('transitionend',(e) => {
makeEnter($(e.currentTarget))
})
makeCurrent($(`.images3 img:nth-child(${x(m+1)})`))
m += 1
},2000)
还可以优化:
优化原则:只要还有代码重复,就有优化的可能
$(`.images3 img:nth-child(${x(m)})`)
这段代码的作用也是获取根据m的值来获取一个jQuery对象,可以优化成:
function getImages(m){
return $(`.images3 img:nth-child(${x(m)})`)
}
最后,主代码就精简成了:
let m = 1
imgsInit()
setInterval(() => {
makeLeave(getImages(m))
.one('transitionend',(e) => {
makeEnter($(e.currentTarget))
})
makeCurrent(getImages(m+1))
m += 1
},2000)
无缝轮播知识点总结:
- 理解状态机(每隔一段时间,根据图片的样式划分到不同的状态)
- CSS需要
position: absolute
和translateX()
的配合 - setInterval()的使用
- 代码的抽象能力