轮播图是网站最常见特效之一,了解底层原理,非常有必要
js实现思路:
1.先获取到需要操作的dom元素
2.鼠标经过离开事件>移入box中显示左右箭头,移出隐藏左右箭头
3.图片轮播到最后一张需要第一张图片来过渡一下,所以就需要动态克隆第一张图片追加到ul
4.动态添加小圆点,并动态设置图片的自定义属性 data-index
5.获取所有小圆点,并动态添加显示current样式,排它显示小圆点
6.通过click事件绑定到小圆点上,通过li图片的data-index属性和盒子的宽度进行相乘达到切换图片位置的目的,注意,ul必须定位,否则没有效果。
7.设置左右按钮切换图片,先定义一个全局变量num,同上,让其和盒子宽度相乘,变量num小于等于li的长度减1
8.设置定时器自动轮播图片,当鼠标移入box设置鼠标移入停止这个定时器。此时到这你的录播图基本可以动起来了,最后我还写了一个缓动动画的函数,让轮播看起来更唯美,不生硬。
HTML结构模块:
注:常见的轮播图至少三层结构:外面一个大盒子,中间ul套li
<!-- 大盒子 -->
<div class="box">
<ul>
<li><img src="./05-轮播图制作/upload/focus.jpg" alt=""></li>
<li><img src="./05-轮播图制作/upload/focus1.jpg" alt=""></li>
<li><img src="./05-轮播图制作/upload/focus2.jpg" alt=""></li>
<li><img src="./05-轮播图制作/upload/focus3.jpg" alt=""></li>
</ul>
<!-- 左箭头 -->
<a href="javascript:;" class="prev">
< </a>
<!-- 右箭头 -->
<a href="javascript:;" class="next"> > </a>
<ol class="circle">
</ol>
</div>
css样式模块
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
a {
text-decoration: none;
color: #fff;
font-size: 30px;
}
.box {
position: relative;
margin: 0 auto;
width: 721px;
height: 455px;
background-color: skyblue;
overflow: hidden;
}
.box ul {
position: absolute;
width: 500%;
}
.box ul li {
float: left;
}
.box .prev {
position: absolute;
top: 50%;
left: 0;
width: 40px;
height: 70px;
transform: translateY(-50%);
text-align: center;
line-height: 60px;
}
.box .next {
position: absolute;
top: 50%;
right: 0;
width: 40px;
height: 70px;
transform: translateY(-50%);
text-align: center;
line-height: 60px;
}
.next,
.prev {
display: none;
background-image: linear-gradient(transparent,
rgba(0, 0, 0, .3));
}
ol li {
width: 8px;
height: 8px;
border-radius: 50%;
border: 2px solid #fff;
float: left;
margin-right: 5px;
cursor: pointer;
}
.circle {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
}
.current {
background-color: #fff;
}
</style>
<script>
// 上一张图片按钮
var prev = document.querySelector('.prev')
// 下一张图片按钮
var next = prev.nextElementSibling
var box = document.querySelector('.box')
var ul = box.children[0]
var circle = document.querySelector('.circle')
// 鼠标移入显示左右箭头
box.addEventListener('mouseenter', function () {
prev.style.display = 'block'
next.style.display = 'block'
clearInterval(timer)
})
// 鼠标移出隐藏左右箭头
box.addEventListener('mouseleave', function () {
prev.style.display = 'none'
next.style.display = 'none'
timer = setInterval(function () {
next.click();
}, 3000)
})
// 克隆第一张到最后面
cloneli = ul.children[0].cloneNode(true)
ul.appendChild(cloneli)
var lis = ul.querySelectorAll('li')
// 动态添加小圆点的li
for (var i = 0; i < lis.length - 1; i++) {
var li = document.createElement('li');
circle.appendChild(li)
// 动态设置图片的自定义属性 data-index
lis[i].setAttribute('data-index', i)
}
// 给第一个默认显示current样式
circle.children[0].classList.add('current')
// 获取所有小圆点li
var cirlis = circle.querySelectorAll('li')
// 排它显示小圆点
for (let i = 0; i < cirlis.length; i++) {
cirlis[i].addEventListener('click', function () {
setCir(cirlis)
this.classList.add('current')
})
}
for (let i = 0; i < cirlis.length; i++) {
// 点击小圆圈切换图片
cirlis[i].addEventListener('click', function () {
// 获取图片li的data-index
var cirIndex = lis[i].getAttribute('data-index')
animate(ul, -lis[i].offsetWidth * cirIndex)
})
}
var num = 0;
var cires = 0;
var flag = true;
next.addEventListener('click', function () {
if (flag) {
flag = false
cires++;
if (num == lis.length - 1) {
num = 0
ul.style.left = 0
}
num++
animate(ul, -lis[0].offsetWidth * num, function () {
flag = true
})
if (cires == lis.length - 1) {
cires = 0
}
setCir(cirlis)
cirlis[cires].classList.add('current')
}
})
prev.addEventListener('click', function () {
if (flag) {
flag = false
if (num == 0) {
num = lis.length - 1
ul.style.left = -num * lis[0].offsetWidth + 'px'
}
num--
animate(ul, -lis[0].offsetWidth * num, function () {
flag = true
})
cires--;
setCir(cirlis)
cires = cires < 0 ? cirlis.length - 1 : cires
cirlis[cires].classList.add('current')
}
})
// 封装排它函数 清除所有小圆点属性
function setCir(cir) {
for (var i = 0; i < cir.length; i++) {
cir[i].classList.remove('current')
}
}
// 自动播放轮播图
var timer = setInterval(function () {
next.click();
}, 3000)
</script>
//animate.js动画函数
function animate(obj, target, callback) {
// console.log(callback); callback = function() {} 调用的时候 callback()
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
// if (callback) {
// // 调用函数
// callback();
// }
callback && callback();
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
-------end