原生javascript 无缝轮播图
结构:
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="utf-8"> <title>轮播图</title> <!-- 引入样式文件--> <link rel="stylesheet" href="css/index.css"> <!-- 引入动画函数--> <script src="js/animate.js"></script> <!-- 引入轮播js文件--> <script src="js/index.js"></script> </head> <body> <!--轮播窗口--> <div class="container"> <!-- 图片盒子--> <div class="img_box"> <img src="images/p1.gif" alt=""> <img src="images/p2.gif" alt=""> <img src="images/p3.gif" alt=""> <img src="images/p4.gif" alt=""> </div> <!-- 左右箭头--> <a href="javascript:" class="left"> < </a> <a href="javascript:" class="right"> > </a> <!-- 小圆点盒子--> <div class="dot_box"></div> </div> </body> </html>
样式
.container {
position: relative;
width: 500px;
height: 300px;
margin: 100px auto;
overflow: hidden;
}
.img_box {
position: absolute;
overflow: hidden;
width: 2500px;
}
.container img {
float: left;
width: 500px;
height: 300px;
}
a {
position: absolute;
top: 50%;
transform: translateY(-50%);
display: none;
width: 24px;
height: 40px;
text-align: center;
text-decoration: none;
color: white;
font-size: 20px;
line-height: 40px;
}
.container a:hover {
background-color: rgba(0, 0, 0, .5);
}
.container:hover a {
display: block;
}
.left {
left: 0;
}
.right {
right: 0;
}
.dot_box {
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
width: 104px;
height: 20px;
}
.dot_box span {
display: inline-block;
float: left;
width: 20px;
height: 20px;
border-radius: 50%;
margin: 0 3px;
text-align: center;
line-height: 20px;
color: deepskyblue;
cursor: pointer;
background-color: rgba(0, 0, 0, .5);
}
.dot_box .on {
color: white;
background-color: #ee3333 !important;
}
动画函数
// 动画原理 // 传入要运动的对象obj 和 运动的距离 target function animate(obj, target, callback) { // callback 为回调函数 比如说 运动完成后要对运动对象进行样式改变 clearInterval(obj.timer); // 优化 //var timer = setInterval(function () { // 这里用var 声明变量 当每次调用时就会声明一个timer 同时也会占用大量内存 // 多个对象同时使用时 可能会产生歧义 obj.timer = setInterval(function () { // 优化 var step = (target - obj.offsetLeft) / 10; // 速度控制 step = step > 0 ? Math.ceil(step) : Math.floor(step); // 取整 防止BUG if (obj.offsetLeft == target) { // clearInterval(timer); clearInterval(obj.timer); // 优化 // if (callback) { // 如果有回调函数 // callback(); // 就进行调用 // } callback && callback(); // 优化 } obj.style.left = obj.offsetLeft + step + 'px'; }, 15) } // 未优化前 多次点击会加速移动 因为调用一次开启一个定时器 多次调用开启了多个定时器 // 解决方法 在运动函数内部 前面添加清除定时器 代码
轮播js
// 加载完成后执行 window.addEventListener('load',function () { // 获取元素 var container = document.querySelector('.container'); var imgBox = document.querySelector('.img_box'); var left = document.querySelector('.left'); var right = document.querySelector('.right'); var dotBox = document.querySelector('.dot_box'); // flag 用于节流阀 防止不断点击左右箭头 使轮播加速 var flag = true; // 控制左右箭头点击时移动距离的变量 var sum = 0; // 控制左右箭头点击时小圆点的样式变化的变量 var sum1 = 0; // 根据图片的张数 动态生成 小圆点 for (var i = 0; i < imgBox.children.length; i++) { // 创建span元素 var span = document.createElement('span'); // 给span添加数字内容 1 2 3 4 span.innerHTML = i + 1; // 设置自定义属性 作为后面的索引 index = i span.setAttribute('index', i); // 将span 元素添加到 小圆点盒子里 dotBox.appendChild(span); } // 获取所有的小圆点 var dots = dotBox.querySelectorAll('span'); // 遍历小圆点 注册点击事件 以及样式 for (var i = 0; i < dots.length; i++) { // 给第一个小圆点添加样式 (默认样式) dots[0].className = 'on'; // 给小圆点注册点击事件 dots[i].addEventListener('click', function () { // 排他思想 先干掉所有小圆点的样式 for (var j = 0; j < dots.length; j++) { dots[j].className = ""; } // 给自己添加样式 this.className = 'on'; // 获得当前小圆点的索引值 var index = this.getAttribute('index'); // 赋值给左右箭头的变量 实现圆点同步 sum = index; sum1 = index; // 设置 flag 为true 防止轮播过程中 突然点小圆点 而flag 还处于 false 的状态 后面轮播不继续 flag = true; // 点击小圆点 时 移动的距离 animate(imgBox, -index * container.offsetWidth); }); } // 克隆第一张图片 var first = imgBox.children[0].cloneNode(true); // 添加到图片盒子 imgBox.appendChild(first); // 右箭头 right.addEventListener('click', function () { // flag 为true 时 执行 if (flag) { // 先将flag 赋值为false 防止不停点击箭头快速轮播 flag = false; // sum 变量控制 轮播循环 if (sum === dots.length) { sum = 0; // 瞬间跳到第一张位置 第一张和最后一张 为用一张图片 跳转时肉眼看不出 imgBox.style.left = '0'; } sum++; // 动画移动 继续轮播~ 动画函数里带有回调函数 动画结束 将flag 赋值为true 下一次点击 就可以继续轮播 animate(imgBox, -sum * container.offsetWidth, function () { flag = true; }); // sum1 控制小圆点样式 sum1++; if (sum1 > dots.length - 1) { sum1 = 0; } for (var i = 0; i < dots.length; i++) { dots[i].className = ''; } dots[sum1].className = 'on'; } }); // 左箭头 left.addEventListener('click', function () { if (flag) { flag = false; if (sum === 0) { sum = dots.length; imgBox.style.left = '-2000px'; } sum--; animate(imgBox, -sum * container.offsetWidth, function () { flag = false; }); sum1--; if (sum1 < 0) { sum1 = dots.length - 1; } for (var i = 0; i < dots.length; i++) { dots[i].className = ''; } dots[sum1].className = 'on'; } }); // 自动轮播 var timer = null; // 自动轮播函数 function autoPlay() { // 计时器 timer = setInterval(function () { right.click(); }, 2000) } // 先调用一次 进入页面时直接轮播 autoPlay(); // 鼠标进入 轮播区 清除计时器 container.addEventListener('mouseenter', function () { clearInterval(timer); }); // 鼠标离开 再次调用自动轮播 开启计时器 container.addEventListener('mouseleave', function () { autoPlay(); }) });