08.26 今天作业是做轮播图
最终效果如下:
一、布局
布局一共有三个部分:图片、切换按钮、分页器。
实现轮播的原理很简单,将图片排成一排,设置一个可使的窗口,窗口的大小为一张图片的大小,其余部分进行hidden,要切换到下一张图片时,将这一排的图片进行位移即可。
接下来是具体代码:
<div class="carousel">
<div class="pic">
<img src="/images/carousel1.jpg" alt="">
<img src="/images/carousel2.jpg" alt="">
<img src="/images/carousel3.jpg" alt="">
<img src="/images/carousel4.jpg" alt="">
<img src="/images/carousel5.jpg" alt="">
</div>
<div class="prev"></div>
<div class="next"></div>
<div class="count">
<ul>
<li class="active"></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>
* {
margin: 0;
padding: 0;
}
.carousel {
margin: 100px auto;
width: 800px;
height: 300px;
overflow: hidden;
position: relative;
}
.pic {
width: 9999px;
position: absolute;
left: 0px;
top: 0;
cursor: pointer;
}
.pic img {
width: 800px;
height: 300px;
float: left;
}
.prev,.next {
width: 40px;
height: 40px;
background-size: 40px 40px;
position: absolute;
top: 130px; /* 300/2 - 40/2 */
cursor: pointer;
}
.prev {
background-image: url(/images/l.png);
left: 20px;
}
.next {
background-image: url(/images/r.png);
right: 20px;
}
.prev:hover,.next:hover {
background-color: rgba(255, 255, 255, 0.8);
border-radius: 50%;
}
.count {
width: 120px;
position: absolute;
bottom: 20px;
left: 340px;
}
.count ul li {
list-style: none;
width: 12px;
height: 12px;
background-color: #fff;
opacity: 0.8;
float: left;
margin-right: 15px;
border-radius: 50%;
cursor: pointer;
}
.count ul li:last-child {
margin-right: 0px;
}
.count ul li:hover {
opacity: 1;
}
.count ul .active {
background-color: #000;
}
二、逻辑
首先引入jq,接着将轮播封装一个方法move,这个方法我们在按钮前后切换和分页器切换时都能用到,所以进行封装。
因为要达到缓慢切入的效果,所以用到计时器,每10毫秒改变图片的left值。
function move(){
clearInterval(timer)
timer = setInterval(() => {
// 改变pic的偏移
var imgLeft = $('.pic')[0].offsetLeft;
var imgWidth = $('.pic img')[now].offsetWidth;
var nowSpeed = (-(now * imgWidth) - imgLeft) / 5;
if(imgLeft <= -(now * imgWidth) + 5){ // 调整偏移
imgLeft = -(now * imgWidth);
}else{
imgLeft = imgLeft;
}
$('.pic').css('left', imgLeft + nowSpeed + 'px')
// console.log(imgLeft)
}, 10);
}
这里简单的画了一张图方便大家理解,也就是说当我们想要显示第二张图时,将pic定位向左移800px(也就是移第一张图的宽度),想要显示第三张图时,将pic定位向左移1600px(也就是移第一张图和第二张图的宽度),以此类推。
想要达到缓慢切入效果,也就是要让他进入的速度由大到小,也就是说让left移动的距离宽度由大到小。
这里举例从一张图切入到第二张图时,此时下标now为1,偏移值为0,宽度为800,我们需要的完整偏移是-800,也就是 -(now * imgWidth)为完整显示第二张需要达到的偏移值。假设我们缓慢偏移,第一次偏移了100px,其实偏移值为-100,还剩下700需要偏移,也就是( -(now * imgWidth)- imgLeft),为了达到缓慢偏移的效果,我们将偏移值除于一个数,来达到每次偏移距离越来越小。
在示例中,我们的每次偏移值都除于5,因此过程如下,当第一次偏移时,now=1,偏移值为0,宽度为800,( -(now * imgWidth)- imgLeft)/ 5 = 160px,第二次偏移时,now=1,偏移值为-160,宽度为800,( -(now * imgWidth)- imgLeft)/ 5 = 128px,第三次偏移时,now=1,偏移值为-288(-160 -128),宽度为800,( -(now * imgWidth)- imgLeft)/ 5 = 102.4px,以此类推……
我们在控制台输出一下nowspeed,可以看到确实是这样。
因此pic每次的偏移值为nowspeed + imgLeft,从而达到缓慢切入的效果。最后测试时注意到每次都没办法达到800偏移占满,因此加上了一个判断条件,让他在最后一小段偏移时直接占满。
确定好轮播方法后就很简单了,在前后切换上,只需要注意下标的变换即可。
// 点击next切换到下一张
$('.next').click(function () {
now++;
if(now == len){
now = 0;
}
// console.log(len)
$('.count li').eq(now).addClass('active').siblings().removeClass('active')
move();
});
// 点击prev切换到上一张
$('.prev').click(function () {
now--;
if(now == -1){
now = len - 1;
}
// console.log(now)
$('.count li').eq(now).addClass('active').siblings().removeClass('active')
move();
});
分页器也是注意下标变化即可。
// 点击分页器跳转
$.each($('.count li'),function (idx,item) {
$(this).click(function () {
$(this).addClass('active').siblings().removeClass('active');
now = idx;
move();
});
})
自动播放需要用到另一个定时器,每一秒钟切换下一张图,实际上就是调用了next的点击方法
// 自动播放
var autoPlayer = setInterval("$('.next').click()",2000)
当鼠标悬停时,停止自动播放,当鼠标移出后继续自动播放
// 鼠标移入悬停
$('.pic').mouseover(function () {
clearInterval(autoPlayer)
});
// 鼠标移出继续播放
$('.pic').mouseout(function () {
autoPlayer = setInterval("$('.next').click()",2000)
});
完整代码如下:
;(function($){
// 定义计时器
var timer = null;
var now = 0; // 当前图的下标
var len = $('.pic img').length; // 获取到当前图片数组长度
// 点击next切换到下一张
$('.next').click(function () {
now++;
if(now == len){
now = 0;
}
// console.log(len)
$('.count li').eq(now).addClass('active').siblings().removeClass('active')
move();
});
// 点击prev切换到上一张
$('.prev').click(function () {
now--;
if(now == -1){
now = len - 1;
}
// console.log(now)
$('.count li').eq(now).addClass('active').siblings().removeClass('active')
move();
});
// 点击分页器跳转
$.each($('.count li'),function (idx,item) {
$(this).click(function () {
$(this).addClass('active').siblings().removeClass('active');
now = idx;
move();
});
})
// 自动播放
var autoPlayer = setInterval("$('.next').click()",2000)
// 鼠标移入悬停
$('.pic').mouseover(function () {
clearInterval(autoPlayer)
});
// 鼠标移出继续播放
$('.pic').mouseout(function () {
autoPlayer = setInterval("$('.next').click()",2000)
});
function move(){
clearInterval(timer)
timer = setInterval(() => {
// 改变pic的偏移
var imgLeft = $('.pic')[0].offsetLeft;
var imgWidth = $('.pic img')[now].offsetWidth;
var nowSpeed = (-(now * imgWidth) - imgLeft) / 5;
if(imgLeft <= -(now * imgWidth) + 5){ // 调整偏移
imgLeft = -(now * imgWidth);
}else{
imgLeft = imgLeft;
}
$('.pic').css('left', imgLeft + nowSpeed + 'px')
console.log(imgLeft)
}, 10);
}
})(jQuery);