需求
1.实现鼠标移入移出时左右键的显示和隐藏
2.点击左键实现切换到上一张,点击右键切换下一张
3.点击序号12345的小图标可以切换到对应的第几张图片,并且当前图片对应的序号被选中(变颜色)
4.没有鼠标点击时可以实现自动播放
代码
body
<div class="all" id="box">
<div id="screen" class="screen">
<ul>
<li><img src="./pic/a.png" alt=""></li>
<li><img src="./pic/b.png" alt=""></li>
<li><img src="./pic/c.png" alt=""></li>
<li><img src="./pic/d.png" alt=""></li>
<li><img src="./pic/e.png" alt=""></li>
</ul>
<ol></ol>
</div>
<div id="arr">
<span id="left"><</span>
<span id="right">></span>
</div>
</div>
css
* {
padding: 0;
margin: 0;
list-style: none;
border: 0;
}
.all {
width: 500px;
height: 300px;
padding: 7px;
border: 1px solid #ccc;
margin: 100px auto;
position: relative;
}
.screen {
width: 500px;
height: 300px;
overflow: hidden;
position: relative;
}
.screen li {
width: 500px;
height: 300px;
overflow: hidden;
float: left;
}
.screen ul {
position: absolute;
left: 0px;
top: 0px;
width: 3000px;
}
.all ol {
position: absolute;
right: 10px;
bottom: 10px;
line-height: 20px;
text-align: center;
}
.all ol li {
float: left;
width: 20px;
height: 20px;
background: #fff;
border: 1px solid #ccc;
margin-left: 10px;
cursor: pointer;
}
.all ol li.current {
background: yellow;
}
#arr {
display: none;
z-index: 1000;
}
#arr span {
width: 40px;
height: 40px;
position: absolute;
left: 5px;
top: 50%;
margin-top: -20px;
background: #000;
cursor: pointer;
line-height: 40px;
text-align: center;
font-weight: bold;
font-family: '黑体';
font-size: 30px;
color: #fff;
opacity: 0.3;
border: 1px solid #fff;
}
#arr #right {
right: 5px;
left: auto;
}
js
// 1.获取节点和设置全局变量
//获取节点
var box = document.querySelector('#box');
var screen = document.querySelector('#screen');
var ul = document.querySelector('ul');
var lis = ul.children;
var arr = document.querySelector('#arr');
var left = document.querySelector('#left');
var right = document.querySelector('#right');
var ol = document.querySelector('ol');
//设置全局变量
var isClick = true; //是否点击
var scWid = screen.offsetWidth; //图片总宽度
var imgIndex = -1; //保存图片索引
// 2.创建ol下的li标签,克隆第一张图片
//创建ol下的li标签
for (var i = 0; i < lis.length; i++) {
var newLi = document.createElement("li");//创建5个li节点
if (i == 0) newLi.classList.add('current')//默认选中第一张,也可以写成:i==0&&newLi.classList.add('current')
newLi.setAttribute("index", i);//自定义属性index保存索引
newLi.innerHTML = i + 1;//第几个li的序号就是几
newLi.onclick = banner;//li被点击时调用banner函数
ol.appendChild(newLi);//追加到ol下
}
//克隆第一张图片
var newImg = lis[0].cloneNode(true);//克隆节点,true是表示克隆lis[0]以及其所有子节点
newImg.style.borderTop = "red solid 1px";//以示不同,后面可以注释掉
ul.appendChild(newImg);//节点追加
// 3.点击ol>li切换图片
function banner() {
imgIndex = this.getAttribute("index");//获取调用者的自定义属性index赋给imgIndex
move(ul, {
left: -(imgIndex * scWid)//实际上就是i*scWid,也就是第几张就把ul的left挪到对应的地方
}, function() {
isClick = true;
})
selectOl();//调用,否则跳转到第i张,对应的ol>li小图标不会相应地被选中(变黄)
}
// 4.获取图片对应的索引值
//这个函数的作用是取消之前选中,并让当前图片对应的索引被选中
function selectOl() {
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].classList.remove("current");
}
ol.children[imgIndex].classList.add("current");
}
// 5.鼠标移入移出,左右键显示与隐藏
box.onmouseover = () => {
arr.style.display = 'block';
}
screen.onmouseout = () => {
arr.style.display = 'none';
}
// 6.点击上一张
/*点击上一张做了什么?
先判断是否点击 如果没有点击(即!isClick=true),那就返回,不要继续往下了
判断:是否当前移到第一张
是:把所有图片显示在左侧(才能继续点击 上一张)
做法:把imgIndex(保存索引的变量)改为第五张的索引(4),
并显示克隆的第六张(让ul的left为-5*scWid)
否:序号自减
调用序号点击的方法:newLi的onclick()
目的是让current选中(黄色显示的)也跟着改变,点击上一张也等价于点击了一次newLi
*/
left.onclick = function() {
if (!isClick) return;
isClick = false;
if (imgIndex == 0) { //第一张:把图片显示在左侧
ul.style.left = -(ul.children.length - 1) * scWid; //5*500
imgIndex = ul.children.length - 1 - 1; //4(下标变成第五张的下标)
} else { //不是第一张:索引自减
imgIndex--;
}
ol.children[imgIndex].onclick();
};
// 7.点击下一张
/*点击下一张做了什么?
先判断是否点击 如果没有点击(即!isClick=true),那就返回不要继续往下了
判断:是否移到了第五张(imgIndex==4)
是:运动到克隆的第六张,到达时(回调)让ul的left为0回到第一张
做法:调用运动函数的封装,让运动主体ul的left为-5*scWid,(5写成imgIndex+1)
在回调中让ul的left为0,isClick变为true
否:索引自增,并调用序号点击的方法
注:调用序号点击方法的时机只要不在第一张/最后一张的if{}中就行
*/
right.onclick = function() {
if (!isClick) return;
isClick = false;
if (imgIndex == ul.children.length - 1 - 1) {
move(ul, {
left: -(imgIndex - 0 + 1) * scWid
}, function() {
isClick = true;
ul.style.left = "0px";
});
selectOl();
imgIndex = 0;
} else {
imgIndex++;
ol.chlidren[imgIndex].onclick();
}
};
// 8.自动播放
/*如何实现自动播放?
在定时器中不断调用right的点击事件即可*/
function autoPlay() {
var times = null;
clearInterval(times);
times = setInterval(() => {
right.onclick();
}, 3000);
}
autoPlay();
/*****运动函数封装*****/
function move(eleObj, objArr, cb) {
//使用前先清除定时器
var timer = null;
clearInterval(timer);
// 设置开关用于判断是否要清除定时器
var onOff = false;
timer = setInterval(() => {
// 遍历元素属性
for (var attr in objArr) {
//获取元素的实时属性值
var tmpPos = parseInt(getPos(eleObj, attr));
// 设置步长
var speed = (objArr[attr] - tmpPos) / 10;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
// 开始运动
if (tmpPos + speed == objArr[attr]) {
onOff = true;
} else {
eleObj.style[attr] = speed + tmpPos + "px";
}
}
}, 30);
}
//获取元素的实时属性值的封装
function getPos(obj, attr) {
if (obj.currentStyle) return obj.currentStyle[attr];
else return getComputedStyle(obj)[attr];
}