在此实现了左右点击,自动轮播,方法简单,有需要的可以看看,有问题欢迎指出:
自动轮播的效果图如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
ul,
ol {
list-style: none;
}
a {
text-decoration: none;
color: #333;
}
.box {
width: 300px;
height: 300px;
margin: 40px 300px;
border: 2px solid blue;
position: relative;
overflow: hidden;
}
.clear::after {
content: "";
display: block;
clear: both;
}
.box ul {
height: 100%;
font-size: 30px;
/* 设置定位是因为后面复制li加到最前面时要显示的是第二张 */
position: absolute;
left: 0;
top: 0;
}
.box ul li {
width: 300px;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
float: left;
}
.box ol {
width: 100%;
display: flex;
justify-content: space-evenly;
align-items: center;
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
}
.box ol li {
width: 20px;
height: 20px;
border-radius: 50%;
border: 1px solid #000;
margin: 0 15px;
cursor: pointer;
}
.box ol li.active {
background-color: rebeccapurple;
}
.box div {
width: 100%;
height: 50px;
position: absolute;
top: 50%;
transform: translateY(-50%);
display: flex;
justify-content: space-between;
align-items: center;
}
.box div a {
font-size: 40px;
color: #000;
font-weight: bold;
}
</style>
</head>
<body>
<div class="box">
<ul class="clear">
<li style="background: hotpink;">图片一</li>
<li style="background: greenyellow;">图片二</li>
<li style="background: rosybrown;">图片三</li>
<li style="background: burlywood;">图片四</li>
<li style="background: seagreen;">图片五</li>
<!-- <li style="background: hotpink;">图片六</li>
<li style="background: greenyellow;">图片七</li>
<li style="background: rosybrown;">图片八</li>
<li style="background: burlywood;">图片九</li>
<li style="background: seagreen;">图片十</li> -->
</ul>
<ol></ol>
<!-- 此处已经实现左右点击 -->
<div>
<a href="JavaScript:;" name="left"> < </a>
<a href="JavaScript:;" name="right"> > </a>
</div>
</div>
<script src="./utils.js"></script>
<script>
var oBox = document.querySelector(".box");
var oUl = document.querySelector("ul");
var oUllis = document.querySelectorAll("ul li");// 一开始的li的长度,不包括后面复制加入的两个li
var oOl = document.querySelector("ol");
var oDiv = oBox.querySelector("div");// 找到oBox下的div
var LiWidth = parseInt(window.getComputedStyle(oUllis[0]).width);// 获取图片的宽度
var index = 1; // 显示当前图片的位置,用来计算移动多少
var time = 0; // 保存自动播放中定时器编号,用于后面清除定时器
var bool1 = true; // 防止点击过快的变量
// 动态生成小圆圈函数
setLi();
// 复制第一个图片和最后一个图片的函数
copyLi();
// 自动播放函数
autoLoop();
// 鼠标移上去停止移动,清除定时器,拿开就重新执行自动播放函数
stopLoop();
// 页面缩小时执行的函数,防止页面隐藏时还在执行程序,进行切换
hidden();
// 左右点击切换
leftRight();
// 点击小圆圈
focus();
</script>
</body>
</html>
utils.js文件中代码如下:
/*
1.动态生成点击用的圆圈li,因为多少图片不固定,所以需要根据图片数量动态生成
2.形成轮播的视觉,复制最后一个放在第一位,然后复制第一个放在最后一位
3.移动函数,设置目标位置,通过不断更新当前位置与目标位置作比较,到达就停止,
也可以设置其他属性(例如宽)的目标值,变化完成就停止
4.写个自动播放函数通过控制移动函数动作,移动函数有个参数是回调函数。
5.回调函数,移动结束后会执行回调函数,用来在移动结束后瞬间回到第一张图片
6.停止播放函数,用鼠标控制播放函数,移上去停止播放,移走鼠标后继续执行播放函数
7.隐藏函数,页面隐藏时停止程序执行,不在切换
8.左右点击函数,此处注意a链接中的href不能不写,否则无法执行js程序
9.点击小圆圈函数,通过自己设置的index属性,找到对应的图片位置进行移动
*/
// 动态生成小圆圈函数
function setLi() {
var str = "";
oUllis.forEach(function (v, key) {
if (key === 0) {
str += `<li index="${key + 1}" class='active'></li>`;
}
else {
str += `<li index="${key + 1}"></li>`;
}
});
oOl.innerHTML = str;
}
// 复制第一个图片和最后一个图片的函数
function copyLi() {
var liFirst = oUllis[0];
var liLast = oUllis[oUllis.length - 1];
// 先克隆第一个和最后一张图片,然后加入到ul中最前面和最后面
var first = liFirst.cloneNode(true);
var last = liLast.cloneNode(true);
oUl.appendChild(first);
oUl.insertBefore(last, liFirst);
// 设置ul宽度,使其不会换行排列
oUl.style.width = ((oUllis.length + 2) * LiWidth) + "px";
// 改变ul的初始位置,使其显示的是第一张图片
oUl.style.left = -LiWidth + 'px';
}
// 传入的参数是标签对象和存放样式的一个对象,对象存储的是运动的目标值,最后是个回调函数
function move(elem, obj, callBack) {
// 存储定时器编号
let time = {};
// 循环遍历对象,有几个键值对就创建几个不同的定时器用来执行不同的样式变化
for (let type in obj) {
let oldVal = 0;
// 透明度是小数,先转换一下
if (type === "opacity") {
// 因为有小数,小数判断相等时有误差,下面的判断难以执行,所以特殊转换
oldVal = parseFloat(window.getComputedStyle(elem)[type]) * 100;
}
else {
oldVal = parseInt(window.getComputedStyle(elem)[type]);
}
// 对象的键值对分别代表样式属性和定时器标号
time[type] = setInterval(function () {
// 分五次运动到目标位置,分母数值越大运动越慢
let val = (obj[type] - oldVal) / 10;
// 设置取整,整数就向上取整,比如0.9直接取1,-0.9取-1,否则下面判断无法等于
val = val > 0 ? Math.ceil(val) : Math.floor(val);
// 更新位置
oldVal += val;
// console.log(oldVal);
// 进行判断属性是不是透明度,因为给的是乘以100后的值,需要除以100,写入标签样式中
if (type === "opacity") {
elem.style[type] = oldVal / 100;
// console.log(oldVal);
}
else {
elem.style[type] = `${oldVal}px`;
}
if (oldVal == obj[type]) {
clearInterval(time[type]);
// delete 操作符用于删除对象的某个属性;如果没有指向这个属性的引用,那它最终会被释放
delete (time[type]);
}
if (Object.keys(time) == 0) {
// 运动停止后执行的函数
callBack();
}
}, 100);
}
}
// 自动播放函数
function autoLoop() {
time = setInterval(function () {
// 加一次就是需要加载下一张图片了
index++;
move(oUl, { left: -index * LiWidth }, moveEnd);
}, 4000); // 时间至少四秒,否则会出现闪烁,执行出问题
}
// 移动结束后要瞬间跑到第一张图片开始那
function moveEnd() {
// 移动结束后重新设置初始值
bool1 = true;
// 如果是最后一张要瞬间转到第二张
if (index == oUllis.length + 1) {
index = 1;
oUl.style.left = -index * LiWidth + 'px';
}
//如果是第一张需要瞬间转到倒数第二张
else if (index == 0) {
index = oUllis.length;
oUl.style.left = (-liWidth * index) + 'px';
}
// 得到小圆圈,用于下面改变样式.先改变图片才会改变焦点,所以要放到最下面
var oOllis = document.querySelectorAll("ol li");
oOllis.forEach(function (val, key) {
// 先清空所有
val.className = "";
// 再根据属性index进行点击样式添加
if (val.getAttribute("index") == index) {
val.className = "active";
}
});
}
// 鼠标移上去停止移动,清除定时器,拿开就重新执行自动播放函数
function stopLoop() {
oBox.addEventListener("mouseover", function () {
clearInterval(time);
});
oBox.addEventListener("mouseout", function () {
autoLoop();
});
}
// 解决页面最小化时,程序一直执行问题
// 通过判断浏览器是否在显示,来停止或执行,自动轮播
// visibilitychange 当页面显示状态改变时,执行的的程序
// document.visibilityState 显示状态数据
// 如果显示 visible
// 如果隐藏 hidden
function hidden() {
// 当页面显示状态发生改变时,触发事件,执行程序
document.addEventListener('visibilitychange', function () {
if (document.visibilityState === 'hidden') {
// 如果显示状态是隐藏,停止定时器,不执行自动轮播
clearInterval(time);
}
else if (document.visibilityState === 'visible') {
// 如果是显示状态,就执行自动轮播函数
autoLoop();
}
})
}
// 左右方向的点击
function leftRight() {
oDiv.addEventListener("click", function (e) {
// 事件兼容
e = e || window.event;
// 事件对象兼容
e.target = e.target || e.srcElement;
if (!bool1) { // 判断是不是初始值,是就返回,不是就执行
return;
}
bool1 = false;
if (e.target.getAttribute("name") == "left") {
index--;
}
else {
index++;
}
move(oUl, { left: -index * LiWidth }, moveEnd);
})
}
// 点击小圆点
function focus() {
oOl.addEventListener("click", function (e) {
// 只有点击li才有效,空白部分没用
if (e.target.tagName == "LI") {
if (!bool1) { return; }
bool1 = false;
// 得到当前圆点的位置,正好对应图片位置
index = e.target.getAttribute("index") * 1;
move(oUl, { left: -index * liWidth }, moveEnd);
}
});
}
此种方法写的自动轮播图大部分都是js自动生成,可扩展性强,随便加入图片可不用改变css样式。
有需要实现点击的轮播图可以参考js实现点击轮播图,有需要扩展的或者不懂的可以跟我一起讨论。