完全自己手写,能力有限,如果有bug请指出
这个做一个简易的轮播图,大概长这个样子,里面的图片就用色块来替代吧
html布局为:
<div class="big">
<a href="javascript:;" class="left"><</a>
<a href="javascript:;" class="right">></a>
<ul class="pic">
<li style="background-color:pink;">1</li>
<li style="background-color:aqua;">2</li>
<li style="background-color:green;">3</li>
<li style="background-color: yellow;">4</li>
<li style="background-color:black;">5</li>
</ul>
<ul class="circle">
</ul>
</div>
主要的元素包括:
一个装下所有东西的大盒子big
左右边 的按钮 left right
轮播图里面的图片 用ul li来装载 pic
下面的小圆圈 cicle 这个地方先不装li 原因下面再说
CSS布局为:
这个地方就不赘述了,没什么难的
<style>
* {
padding: 0;
margin: 0;
}
.big {
position: relative;
width: 500px;
height: 350px;
margin: 100px auto;
/* background-color: red; */
overflow: hidden;
}
.left {
position: absolute;
top: 175px;
left: 0;
z-index: 2;
display: none;
}
.right {
display: none;
position: absolute;
top: 175px;
right: 0;
z-index: 2;
}
.circle {
position: absolute;
bottom: 30px;
left: 50%;
height: 20px;
transform: translate(-50%, 0);
z-index: 2;
}
.circle li {
list-style: none;
float: left;
margin-right: 10px;
width: 20px;
height: 20px;
border-radius: 10px;
background-color: gray;
}
.pic {
position: absolute;
top: 0;
left: 0;
height: 350px;
z-index: 1;
}
.pic li {
float: left;
list-style: none;
height: 350px;
width: 500px;
}
</style>
JS实现
我们要实现的功能为:
1.鼠标放上去按钮浮现 鼠标移开按钮隐藏
2.下面的小圆圈个数与轮播图图片个数动态对应,不需要手动设置
3.点击按钮,轮播图向左或向右跳转,且下面的小圆圈的颜色与轮播图的图片对应(例如播放到第二张图 第二个小圆圈为红色)
4.点击下面的小圆圈也能实现跳转
5.鼠标不放上去自动播放 放上去就停止播放
引入元素
var right = document.querySelector('.right');
var left = document.querySelector('.left')
var pic = document.querySelector('.pic')
var cicle = document.querySelector('.circle')
var big = document.querySelector('.big')
var step = pic.children[0].offsetWidth;
var num = pic.children.length
这个地方
step对应的是轮播图中每个图片的大小,也就是一次运动的移动距离
num是轮播图中有多少个图片
1.鼠标放上去按钮浮现 鼠标移开按钮隐藏
这个很简单,给最大盒子big添加事件,当鼠标进入big时,显示left right按钮 ,当鼠标离开时隐藏
big.addEventListener('mouseenter', function () {
left.style.display = 'block'
right.style.display = 'block'
})
big.addEventListener('mouseleave', function () {
left.style.display = 'none'
right.style.display = 'none'
})
2.下面的小圆圈个数与轮播图图片个数动态对应
主要是一个for循环,循环次数等于轮播图图片数量,每次循环创造一个li,添加到circle的子元素中
for (var i = 0; i < num; i++) {
var lii = document.createElement('li')
circle.appendChild(lii)
}
circle.style.width = 30 * num + 'px'
pic.style.width = step * (num + 1) + 'px'
circle.children[0].style.backgroundColor = 'red'
下面三句话的意思是:
由于是动态的 css中没有指定pic和circle的大小,这里动态赋予
一开始肯定处于第一张图片,故第一个小圆圈为红色
3.点击按钮,轮播图向左或向右跳转,且下面的小圆圈的颜色与轮播图的图片对应
首先介绍一个函数,这个函数的作用是,将obj对象移动到target位置,在移动前执行first函数,移动后执行callback函数,这两个函数可以为空。
function fn(obj, target, first, callback) {
if (obj.timer) {
clearInterval(obj.timer)
}
if (first) {
first()
}
obj.timer = setInterval(function () {
//移动先快后慢
var distance = (target - obj.offsetLeft) / 10;
//考虑到了distance为负数的情况
distance = distance > 0 ? Math.ceil(distance) : Math.floor(distance)
obj.style.left = obj.offsetLeft + distance + 'px'
if (obj.offsetLeft == target) {
clearInterval(obj.timer)
if (callback) {
callback()
}
}
}, 20)
}
值得注意的是,这里distance的赋值是递减的,也就是说移动会是先快后慢
这个地方我们还想实现一个功能:
当我到达最后一张图的时候,我再点击right按钮,我希望其还是往后面滚动,但是实际上已经到了第一张图片,即无缝滚动
思路是,我一开始给pic的最后再加一张图片,这个图片与第一张图片一模一样,在这个例子中,pic有五个图片,但是实际上有六个,因为我在最后再加了一个与第一张完全一样的图片:
接下来的讲解中我将用数字代表这些图片
var last = pic.children[0].cloneNode(true)
pic.appendChild(last);
为了完成轮播图的功能,我再设定一个变量flag,含义为当前的轮播图播放到哪一张图了
var flag = 0
以right按钮为例,给其添加点击事件:
right.addEventListener('click', function () {
if (flag == num) {
flag = 0;
pic.style.left = 0
}
if (flag < num - 1) {
flag = parseInt(flag) + parseInt(1)
fn(pic, -step * flag, function () {
circle.children[flag].style.backgroundColor = 'red';
circle.children[flag - 1].style.backgroundColor = 'gray'
})
}
else if (flag == num - 1) {
flag = parseInt(flag) + parseInt(1)
fn(pic, -step * flag, function () {
circle.children[0].style.backgroundColor = 'red';
circle.children[num - 1].style.backgroundColor = 'gray'
}, function () {
})
}
})
这里有一些判断语句:
第一个if表示,当我已经到达最后一张(第二个1),让pic快速的,没有动画的移动到第一张的位置,这样就能实现无缝播放的功能
第二个if表示,当我到达除最后一张(5)的前几张时,先给flag+1,示意接下来要去下一张,然后让pic运动到下一张位置,最后让后面一张的小圆圈变红,前一张的小圆圈变灰
当我移动到5时,接下来移动应该到 第二个1 ,但是应该是第一个小圆圈变红,最后一个小圆圈边灰
left按钮类似
left.addEventListener('click', function () {
if (flag > 0) {
flag -= 1
fn(pic, -step * flag, function () {
circle.children[flag].style.backgroundColor = 'red'
circle.children[flag + 1].style.backgroundColor = 'gray'
})
}
else if (flag == 0) {
flag = num;
pic.style.left = -step * (num) + 'px';
flag--
fn(pic, -step * flag, function () {
circle.children[num - 1].style.backgroundColor = 'red'
circle.children[0].style.backgroundColor = 'gray'
})
}
})
这里少了一个判断语句,是因为其到达 第一个1时 不需要再往前走了,而是直接马上回到第二个1即可。
4.点击下面的小圆圈也能实现跳转
用for循环给每一个小圆圈赋予响应。
为了知道点的是哪个小圆圈,给每个li加了一个自定义变量index,每次点击时,可以根据index知道需要运动多少,给flag赋值多少
for (var i = 0; i < circle.children.length; i++) {
circle.children[i].setAttribute('index', i);
circle.children[i].addEventListener('click', function () {
var index = this.getAttribute('index');
fn(pic, -step * index)
for (var i = 0; i < circle.children.length; i++) {
circle.children[i].style.backgroundColor = 'gray';
}
this.style.backgroundColor = 'red'
flag = index;
})
}
5.鼠标不放上去自动播放 放上去就停止播放
这个地方很简单,自动播放就效果而已其实就是,每隔一段时间点击了right一次,那我们可以认为模拟这一动作
由于进入页面就要开始播放,故需要定义:
var animi = setInterval(function () {
right.click()
}, 2000)
也就是2s执行一次right.click(),相当于模拟了一次点击right
再在big事件中添加事件:
big.addEventListener('mouseenter', function () {
left.style.display = 'block'
right.style.display = 'block'
clearInterval(animi)
animi = null
})
big.addEventListener('mouseleave', function () {
left.style.display = 'none'
right.style.display = 'none'
animi = setInterval(function () {
right.click()
}, 2000)
})
完全实现功能
完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
.big {
position: relative;
width: 500px;
height: 350px;
margin: 100px auto;
/* background-color: red; */
overflow: hidden;
}
.left {
position: absolute;
top: 175px;
left: 0;
z-index: 2;
display: none;
}
.right {
display: none;
position: absolute;
top: 175px;
right: 0;
z-index: 2;
}
.circle {
position: absolute;
bottom: 30px;
left: 50%;
height: 20px;
transform: translate(-50%, 0);
z-index: 2;
}
.circle li {
list-style: none;
float: left;
margin-right: 10px;
width: 20px;
height: 20px;
border-radius: 10px;
background-color: gray;
}
.pic {
position: absolute;
top: 0;
left: 0;
height: 350px;
z-index: 1;
}
.pic li {
float: left;
list-style: none;
height: 350px;
width: 500px;
}
</style>
</head>
<body>
<div class="big">
<a href="javascript:;" class="left"><</a>
<a href="javascript:;" class="right">></a>
<ul class="pic">
<li style="background-color:pink;">1</li>
<li style="background-color:aqua;">2</li>
<li style="background-color:green;">3</li>
<li style="background-color: yellow;">4</li>
<li style="background-color:black;">5</li>
</ul>
<ul class="circle">
</ul>
</div>
<script>
var right = document.querySelector('.right');
var left = document.querySelector('.left')
var pic = document.querySelector('.pic')
var circle = document.querySelector('.circle')
var big = document.querySelector('.big')
var step = pic.children[0].offsetWidth;
var num = pic.children.length
for (var i = 0; i < num; i++) {
var lii = document.createElement('li')
circle.appendChild(lii)
}
circle.style.width = 30 * num + 'px'
pic.style.width = step * (num + 1) + 'px'
circle.children[0].style.backgroundColor = 'red'
var last = pic.children[0].cloneNode(true)
pic.appendChild(last);
console.log(pic);
var flag = 0
var animi = setInterval(function () {
right.click()
}, 2000)
for (var i = 0; i < circle.children.length; i++) {
circle.children[i].setAttribute('index', i);
circle.children[i].addEventListener('click', function () {
var index = this.getAttribute('index');
fn(pic, -step * index)
for (var i = 0; i < circle.children.length; i++) {
circle.children[i].style.backgroundColor = 'gray';
}
this.style.backgroundColor = 'red'
flag = index;
})
}
big.addEventListener('mouseenter', function () {
left.style.display = 'block'
right.style.display = 'block'
clearInterval(animi)
animi = null
})
big.addEventListener('mouseleave', function () {
left.style.display = 'none'
right.style.display = 'none'
animi = setInterval(function () {
right.click()
}, 2000)
})
right.addEventListener('click', function () {
if (flag == num) {
flag = 0;
pic.style.left = 0
}
if (flag < num - 1) {
flag = parseInt(flag) + parseInt(1)
fn(pic, -step * flag, function () {
circle.children[flag].style.backgroundColor = 'red';
circle.children[flag - 1].style.backgroundColor = 'gray'
})
}
else if (flag == num - 1) {
flag = parseInt(flag) + parseInt(1)
fn(pic, -step * flag, function () {
circle.children[0].style.backgroundColor = 'red';
circle.children[num - 1].style.backgroundColor = 'gray'
}, function () {
})
}
})
left.addEventListener('click', function () {
if (flag > 0) {
flag -= 1
fn(pic, -step * flag, function () {
circle.children[flag].style.backgroundColor = 'red'
circle.children[flag + 1].style.backgroundColor = 'gray'
})
}
else if (flag == 0) {
flag = num;
pic.style.left = -step * (num) + 'px';
flag--
fn(pic, -step * flag, function () {
circle.children[num - 1].style.backgroundColor = 'red'
circle.children[0].style.backgroundColor = 'gray'
})
}
})
function fn(obj, target, first, callback) {
if (obj.timer) {
clearInterval(obj.timer)
}
if (first) {
first()
}
obj.timer = setInterval(function () {
var distance = (target - obj.offsetLeft) / 10;
distance = distance > 0 ? Math.ceil(distance) : Math.floor(distance)
obj.style.left = obj.offsetLeft + distance + 'px'
if (obj.offsetLeft == target) {
clearInterval(obj.timer)
if (callback) {
callback()
}
}
}, 20)
}
</script>
</body>
</html>