这里是html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>淘宝轮播图做法</title>
<link rel="stylesheet" href="./css/index.css">
<!-- 引入动画js,必须协助index.js的上面 -->
<script src="./js/animate.js"></script>
<script src="./js/index.js"></script>
</head>
<body>
<div class="tb-promo">
<!-- 左侧按钮箭头 -->
<div class="prev">←</div>
<!-- 右侧按钮箭头 -->
<div class="next">→</div>
<ul class="focus">
<li><img src="images/focus.png" alt=""></li>
<li><img src="images/focus1.jpeg" alt=""></li>
<li><img src="images/focus2.png" alt=""></li>
<li><img src="images/focus3.jpeg" alt=""></li>
</ul>
<!-- 小圆点 -->
<ol class="promo-nav">
</ol>
</div>
</body>
</html>
需要引入 index.css
* {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
.tb-promo {
position: relative;
width: 520px;
height: 280px;
background-color: pink;
margin: 100px auto;
overflow: hidden;
}
.tb-promo .focus {
position: absolute;
width: 2601px;
height: 280px;
background-color: pink;
}
.tb-promo ul li {
float: left;
}
.tb-promo ul li img {
width: 520px;
height: 280px;
}
/* 并集选择器可以集体声明相同的样式 */
.prev,
.next {
display: none;
position: absolute;
/* 绝对定位的盒子垂直居中 */
top: 50%;
margin-top: -15px;
/* 加了绝对定位的盒子可以直接设置高度和宽度 */
width: 20px;
height: 30px;
background: rgba(0, 0, 0, .3);
text-align: center;
line-height: 30px;
color: #fff;
text-decoration: none;
z-index: 2;
}
.prev {
left: 0;
/* border-radius: 15px; */
border-top-right-radius: 15px;
border-bottom-right-radius: 15px;
}
.next {
/* 如果一个盒子既有left属性也有right属性,则默认会执行 left属性 同理 top bottom 会执行 top */
right: 0;
/* border-radius: 15px; */
border-top-left-radius: 15px;
border-bottom-left-radius: 15px;
}
.promo-nav {
position: absolute;
bottom: 15px;
left: 50%;
margin-left: -35px;
width: 70px;
height: 13px;
/* background-color: pink; */
background: rgba(255, 255, 255, .3);
border-radius: 7px;
}
.promo-nav li {
float: left;
width: 8px;
height: 8px;
background-color: #fff;
border-radius: 50%;
margin: 3px;
}
/* 不要忘记选择器权重的问题 */
.promo-nav .selected {
background-color: #ff5000;
}
还需要引入两个js文件
index.js 和 animate.js
window.addEventListener('load', function () {
var tbPromo = document.querySelector('.tb-promo');
var prevd = document.querySelector('.prev');
var next = document.querySelector('.next');
// 获取宽度
var tbPromoWidth = tbPromo.offsetWidth;
// 1鼠标经过轮播图显示左右按钮,离开隐藏左右按钮
tbPromo.addEventListener('mouseenter', function () {
prevd.style.display = 'block';
next.style.display = 'block';
// 鼠标经过停止定时器
clearInterval(timer);
timer = null; //清空定时器
});
tbPromo.addEventListener('mouseleave', function () {
prevd.style.display = 'none';
next.style.display = 'none';
// 鼠标离开开启定时器
timer = setInterval(function () {
// 手动调用事件
next.click();
}, 2000);
});
//2 动态生成小圆圈,有几张图就生成几个小圆圈
var ul = tbPromo.querySelector('ul');
var ol = tbPromo.querySelector('.promo-nav');
// console.log(ul.children.length);
for (var i = 0; i < ul.children.length; i++) {
// 创建一个小li
var li = this.document.createElement('li');
// 记录当前小圆圈的索引号,通过自定义属性来做
li.setAttribute('index', i);
// 把li插入到ol里面
ol.appendChild(li);
// 生成小圆圈的时候,直接绑定点击事件
li.addEventListener('click', function () {
//3 拍他思想,把全部的排除selected
for (var i = 0; i < ol.children.length; i++) {
var li = ol.children[i];
li.className = '';
}
this.className = 'selected';
// 4点击小圆圈移动图片
// ul的移动距离是小圆圈的索引号*宽度
// 点击某个小li就会获取他的索引号
var index = this.getAttribute('index');
// 当我们点击某个远点,要把index给num
num = index;
circle = index;
animate(ul, -index * tbPromoWidth);
});
}
// 把ol里面的第一个li设置为选定状态
ol.children[0].className = 'selected';
// 6克隆第一张图片放到放到最后面
var firstLi = ul.children[0].cloneNode(true);
ul.appendChild(firstLi);
// 7 点击右侧按钮 图片滚动一张
var num = 0; //图片的索引号
var circle = 0; //控制小圆圈的变化
// 节流阀
var flag = true;
next.addEventListener('click', function () {
if (flag == true) {
flag = false;
// (图片无缝滚动)如果走到了最后一张,ul快速复原 left设为0
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * tbPromoWidth, function () {
flag = true;
});
// 8 走到哪个哪个小圆点变色,其他不变色
circle++;
// 如果circle = 4,置为0
circle = circle == ol.children.length ? 0 : circle;
circlePageChange();
}
});
// 9 点击左侧按钮 图片滚动到上一张
prevd.addEventListener('click', function () {
if (flag == true) {
flag = false;
// (图片无缝滚动)如果走到了最后一张,ul快速复原 left设为0
if (num == 0) {
num = ul.children.length - 1;
ul.style.left = -num * tbPromoWidth + 'px';
}
num--;
animate(ul, -num * tbPromoWidth, function () {
flag = true;
});
// 8 走到哪个哪个小圆点变色,其他不变色
circle--;
// 如果circle < 0,置为第一张圆圈要改为最后一个小圆圈
circle = circle < 0 ? ol.children.length - 1 : circle;
circlePageChange();
}
});
// circle位置改变
function circlePageChange() {
for (var i = 0; i < ol.children.length; i++) {
var li = ol.children[i];
if (i == circle) {
li.className = 'selected';
} else {
li.className = '';
}
}
}
// 10 鼠标未在轮播图上自动滚动 2s调用一次
var timer = this.setInterval(function () {
// 手动调用事件
next.click();
}, 2000);
});
animate.js封装了滚动动画
// obj目标对象,target目标位置
// 给不同的元素指定不同的定时器
function animate(obj, targt, callback) {
// 当我们不断地点击按钮,元素的速度越来越快,因为开启了太多定时器
// 解决方案,让元素只有一个定时器(清除上一个定时器,只保留当前的定时器)
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 步长值
// 把步长值改为正直 ,向上取整
var step = (targt - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == targt) {
// 停止定时器
clearInterval(obj.timer);
// if (callback) {
// callback(); //回调函数
// }
callback && callback();
}
// 把每次+1这个步长值逐渐变小,步长公式 (目标位置值 - 现在的位置)/10
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
大功告成。自己把代码粘贴下来,放到对应的文件中即可
demo在此