效果粗略演示:
当鼠标经过图片时左右两侧的箭头才显示,且图片停止轮播;当鼠标点击箭头或小圆点时会跳到相对应的图片;当鼠标离开后图片继续无限循环播放
核心原理:
在一个大的div父盒子里放一个ul,ul里有若干个li(用浮动让li排成一行),每个li里面放一张图片,再封装一个动画函数让ul在水平方向移动,同时用overflow:hidden将溢出父盒子的部分隐藏起来
在设置li的浮动时,先给ul一个较大的宽度(ul的宽度会溢出父盒子),否则浮动的li会掉下来无法排成一行
基本HTML结构:
<div class="father">
<img class="arrow_l" src="images/arrow_l.png" alt="">
<img class="arrow_r" src="images/arrow_r.png" alt="">
<ul>
<li>
<img src="images/img_1.jpg" alt="">
</li>
<li>
<img src="images/img_2.jpg" alt="">
</li>
<li>
<img src="images/img_3.jpg" alt="">
</li>
<li>
<img src="images/img_4.jpg" alt="">
</li>
<li>
<img src="images/img_5.jpg" alt="">
</li>
</ul>
<!-- 左下角的小圆点,但现在还不确定有几个小圆点 -->
<ol class="circle">
</ol>
</div>
封装动画函数
函数的参数分别为调用者,目标位置,回调函数(如果有回调函数就执行,没有就不执行),调用者从原位置移动到目标位置就停止
这里运用了缓动动画效果,即运动速度刚开始较快,然后逐渐变慢,直到停止(不用缓动效果的话,整个运动过程就会显得较为生硬)
// 封装动画函数animate
function animate(obj, target, back) {
var timer = setInterval(function() {
if (obj.offsetLeft == target) {
clearInterval(timer);
if (back) {
back();
}
}
var everyStep = (target - obj.offsetLeft) / 10;
everyStep = everyStep > 0 ? Math.ceil(everyStep) : Math.floor(everyStep);
obj.style.left = obj.offsetLeft + everyStep + 'px';
}, 15);
}
图片的滑动
利用封装好的动画函数animate( ul , - fatherWidth * num )即可实现,调用对象是ul,fatherWidth是父盒子的宽度,num为当前显示的图片的索引号,fatherWidth和num的乘积就是整个ul要移动的距离
左右两侧箭头
等鼠标经过父盒子时箭头显现,轮播暂定
鼠标离开父盒子时箭头消失,重新开始轮播
.arrow_l,
.arrow_r {
position: absolute;
display: none;
/* ul和箭头都定位了,箭头被压在了下面,要提上来 */
z-index: 2;
}
// 给父盒子注册鼠标进入事件,鼠标进入时箭头显现,同时控制图片播放的定时器停止
father.addEventListener('mouseenter', function() {
arrow_l.style.display = 'block';
arrow_r.style.display = 'block';
clearInterval(timer_1);
timer_1 = null;
})
// 给父盒子注册鼠标离开事件
father.addEventListener('mouseleave', function() {
arrow_l.style.display = 'none';
arrow_r.style.display = 'none';
timer_1 = setInterval(function() {
arrow_r.click();
}, 2000);
})
小圆点:
这里有个问题,就是小圆点的个数应该是和图片的张数是一致的,所以我们不能直接定义小圆点的个数,而应该让圆点个数随着图片张数的变化而变化(顺便在循环中为小圆点注册鼠标点击事件)
在js中定义变量current_index,表示当前小圆点的索引号
当鼠标点击小圆点时,当前图片的索引号和小圆点的索引号是相同的
for (var i = 0; i < ul.children.length; i++) {
var li = document.createElement('li');
ol.appendChild(li);
li.setAttribute('index', i);
// 默认第一个小圆圈的颜色为白色
ol.children[0].className = 'current_color';
// 顺便为小圆点注册事件
li.addEventListener('click', function() {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
this.className = 'current_color';
var current_index = this.getAttribute('index');
num = current_index;
circle = current_index;
animate(ul, -current_index * father_Width);
})
}
左箭头控制图片向右移动
// 每次点击左箭头时,图片向右轮播
arrow_l.addEventListener('click', function() {
if (flag) {
flag = false;
if (num == 0) {
num = ul.children.length - 1;
// 一定要加px,否则最左图片切换到最右图片时不连贯
ul.style.left = -num * father_Width + 'px';
}
num--;
animate(ul, -num * father_Width, function() {
flag = true;
});
circle--;
circle = circle < 0 ? ol.children.length - 1 : circle;
circleChange();
}
})
右箭头控制图片向左移动
// 每次点击右箭头时,图片向左轮播
arrow_r.addEventListener('click', function() {
if (flag) {
flag = false;
if (num == ul.children.length - 1) {
num = 0;
ul.style.left = 0;
}
num++;
animate(ul, -num * father_Width, function() {
flag = true;
});
circle++;
if (circle == ol.children.length) {
circle = 0;
}
circleChange();
}
})
小技巧
为了使第5张图片和第1张图片之间的过渡显得更加连贯自然,在第6张图片的位置加了一张图片(和第1张图片一模一样)
① 播放的当前图片为最后一张图片时(即为第6张时),利用定位迅速让当前图片变成第1张
if (num == ul.children.length - 1) {
num = 0;
ul.style.left = 0;
}
② 如果要使鼠标点击左箭头让当前图片从第1张切换到第5张,那么在当前图片为第1张的时候,利用定位迅速让当前图片变成第6张
if (num == 0) {
num = ul.children.length - 1;
ul.style.left = -num * father_Width + 'px';
}
注意:上面的定位一定要加单位px,否则就会出现下面这种过渡不连贯的效果
图片自动轮播
var timer_1 = setInterval(function() {
arrow_r.click();
}, 1500);
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。