效果图:
需求分析:
- 根据图片的数量生成相同的小圆点,类名是slider-ctrl-con
- 显示第一个图片,同时第一个小圆点高亮,类名是:slider-ctrl-con current;
- 点击prev显示上一张图片,同时对应小圆点高亮
- 点击next显示下一张图片,同时对应小圆点高亮
- 点击小圆点,切换到对应的图片,同时小圆点高亮
- 可以自动轮播(每隔3000ms自动切换到下一张)
- 鼠标移入slider盒子,停止轮播
- 鼠标移出slider盒子,继续轮播
源代码:
- HTML部分
<div class="slider" id="slider">
<div class="slider-img">
<ul>
<li><a href="#"><img src="images/1.jpg" alt=""/></a></li>
<li><a href="#"><img src="images/2.jpg" alt=""/></a></li>
<li><a href="#"><img src="images/3.jpg" alt=""/></a></li>
<li><a href="#"><img src="images/4.jpg" alt=""/></a></li>
<li><a href="#"><img src="images/5.jpg" alt=""/></a></li>
<li><a href="#"><img src="images/6.jpg" alt=""/></a></li>
</ul>
</div>
<div class="slider-ctrl">
<span class="prev" id="prev"></span>
<span class="next" id="next"></span>
</div>
</div>
- css部分
<style>
/* */
* {
margin: 0;
padding: 0;
}
.slider {
width: 310px;
height: 265px;
margin: 100px auto;
position: relative;
overflow: hidden; /* 超出部分隐藏 */
}
.slider-img {
width: 310px;
height: 220px;
}
ul {
list-style: none;
}
li {
position: absolute; /* 相对.slider进行定位 */
top: 0;
left: 0;
}
.slider-ctrl {
text-align: center;
padding-top: 10px;
}
.slider-ctrl-con {
display: inline-block;
width: 24px;
height: 24px;
background: url(../images/icon.png) no-repeat -24px -780px;
text-indent: -99999px;
margin: 0 5px;
cursor: pointer;
}
.slider-ctrl-con.current {
background-position: -24px -760px; /* 小圆点所在精灵图中的位置 */
}
.prev,.next {
position: absolute;
top: 40%;
width: 30px;
height: 35px;
background: url(../images/icon.png) no-repeat; /* prev左箭头所在精灵图中的位置 */
}
.prev {
left: 10px;
}
.next {
right: 10px;
background-position: 0 -44px; /* next右箭头所在精灵图中的位置 */
}
</style>
- JavaScript部分
- 为了使代码简洁,先单独封装几个函数
<script>
// 根据id获取元素
function $id(id){
return document.getElementById(id);
}
// 返回指定dom节点的attr样式值
function getStyle(dom,attr){
if(window.getComputedStyle){
// 说明有getComputedStyle方法
return window.getComputedStyle(dom,null)[attr]
}else{
return dom.currentStyle[attr]
}
}
// 封装一个缓动的动画函数
function animate(dom,json,callback){
/*
dom:要运动的节点
json:要运动的样式名
callback:运动完成的回调函数
*/
clearInterval(dom.timer);//要用定时器,先清定时器
//要运动的定时器
dom.timer = setInterval(function(){
var flag = true;
//json有几个属性,就要运动几次
for(var attr in json){
//获取当前位置
var current = parseInt(getStyle(dom,attr));
// 计算速度
var speed = json[attr] - current > 0 ? Math.ceil((json[attr]-current)/10):Math.floor((json[attr]-current)/10);
//计算下一个位置
var next = current + speed;
//定位元素
dom.style[attr] = next+'px';
//判断是否达到目标
if(next != json[attr]){
flag = false;
}
}
if(flag){
clearInterval(dom.timer);
}
},20)// 每20毫秒
}
// 封装一个函数:第index个小圆点高亮
function light(){
// 所有都不高亮
for(var i=0; i<imgArr.length; i++){
spanArr[i].className = "slider-ctrl-con";
// 只有index高亮
spanArr[index].className = "slider-ctrl-con current";
}
}
// 把看下一张封装成一个函数
function autoplay(){
var next = index+1;
if(next>imgArr.length-1){
next = 0;
}
// 当前要看的图的索引是index,马上要看的图的索引是next
// next是下一张,必须在右边
imgArr[next].style.left = width+"px";
// next来中间显示,index去左边
animate(imgArr[next],{left:0})
animate(imgArr[index],{left:-width})
// 更新当前显示的图片的索引
index = next;
// 点亮对应的小圆点
light()
}
</script>
- 主体部分,需要用到封装的函数调用即可
<script>
// 获取元素
var sliderDiv = $id('slider'); //总容器
var imgArr = sliderDiv.children[0].children[0].children; //所有图片li集合
var prevBtn = $id('prev'); //上一张按钮
var nextBtn = $id('next'); //下一张按钮
var ctrlDiv = prevBtn.parentNode; //prevBtn的父节点,即控制按钮所在容器
// 定义一个变量,记录当前显示的是图片的索引/小圆点的索引
var index = 0; //索引最大长度为imgArr.length-1
// 定义一个变量,记录一个图片的宽度
var width = sliderDiv.offsetWidth;
// 中间:left:0
// 左边:left:-width
// 右边:left:width
// 1 根据图片的数量
/*
因为insertBefore是向前一一插入span小圆点的,
所以索引需要倒过来赋值才能得到正序索引
*/
for(var i=imgArr.length-1; i>=0; i--){
// 生成相同的小圆点
var newPoint = document.createElement('span');
// 设置类名为slider-ctrl-con
newPoint.className = "slider-ctrl-con";
// innerHTML记录当前小圆点的索引
newPoint.innerHTML = i;
//将span小圆点放入slider-ctrl盒子中
ctrlDiv.insertBefore(newPoint,ctrlDiv.children[0]);
// 所有图片都去右边
imgArr[i].style.left = width + 'px';
}
// 获取所有控制按钮的集合
var spanArr = ctrlDiv.children; // 包括小圆点和左右箭头,但是小圆点在前面
// 2 第一个图片在中间
imgArr[index].style.left = 0;
light();
// 把小圆点和左右箭头的点击事件委托给ctrlDiv
ctrlDiv.onclick = function(e){
e = window.event || e; //浏览器兼容写法
var target = e.target || e.srcElement; //浏览器兼容写法
if(target.className == 'prev'){
// 3 点击prev显示上一张图片,同时对应小圆点高亮
var next = index - 1;
if(next < 0){//如果这已经是第一张了,则跳转到最后一张
next = imgArr.length-1;
}
// 当前要看的图的索引是index,马上要看的图的索引是next
// next是上一张,必须在左边
imgArr[next].style.left = -width+'px';
// next来中间显示,index去右边
animate(imgArr[next],{left:0})
animate(imgArr[index],{left:width});
// 更新当前显示的图片的索引
index = next;
// 点亮对应的小圆点
light();
}else if(target.className == 'next'){
// 4 点击next显示下一张图片,同时对应小圆点高亮
autoplay();
}else if(target.className.indexOf('slider-ctrl-con')>-1){
// 5 点击小圆点,切换到对应的图片,同时小圆点高亮
var next = parseInt(target.innerHTML); //要看的图片的索引,字符串,转数值
if(next>index){
// 类似下一张,next在右边
imgArr[next].style.left = width+"px";
// next来中间显示,index去左边
animate(imgArr[next],{left:0})
animate(imgArr[index],{left:-width});
// 更新当前显示的图片的索引
index = next;
// 点亮对应的小圆点
light()
}else if(next<index){
// 类似上一张,next在左边
imgArr[next].style.left = -width+"px";
// next来中间显示,index去右边
animate(imgArr[next],{left:0})
animate(imgArr[index],{left:width});
// 更新当前显示的图片的索引
index = next;
// 点亮对应的小圆点
light()
}
}
}
// 6 可以自动轮播
sliderDiv.timer = setInterval(autoplay,3000);
// 7 鼠标移入slider盒子,停止轮播
sliderDiv.onmouseenter = function(){
clearInterval(sliderDiv.timer);
}
// 8 鼠标移出slider盒子,继续轮播
sliderDiv.onmouseleave = function(){
clearInterval(sliderDiv.timer);
sliderDiv.timer = setInterval(autoplay,3000);
}
</script>
- 总代码
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
/* */
* {
margin: 0;
padding: 0;
}
.slider {
width: 310px;
height: 265px;
margin: 100px auto;
position: relative;
overflow: hidden;
/* 超出部分隐藏 */
}
.slider-img {
width: 310px;
height: 220px;
}
ul {
list-style: none;
}
li {
position: absolute;
/* 相对.slider进行定位 */
top: 0;
left: 0;
}
.slider-ctrl {
text-align: center;
padding-top: 10px;
}
.slider-ctrl-con {
display: inline-block;
width: 24px;
height: 24px;
background: url(./images/icon.png) no-repeat -24px -780px;
text-indent: -99999px;
margin: 0 5px;
cursor: pointer;
}
.slider-ctrl-con.current {
background-position: -24px -760px;
/* 小圆点所在精灵图中的位置 */
}
.prev,
.next {
position: absolute;
top: 40%;
width: 30px;
height: 35px;
background: url(./images/icon.png) no-repeat;
/* prev左箭头所在精灵图中的位置 */
}
.prev {
left: 10px;
}
.next {
right: 10px;
background-position: 0 -44px;
/* next右箭头所在精灵图中的位置 */
}
</style>
</head>
<body>
<div class="slider" id="slider">
<div class="slider-img">
<ul>
<li><a href="#"><img src="images/1.jpg" alt="" /></a></li>
<li><a href="#"><img src="images/2.jpg" alt="" /></a></li>
<li><a href="#"><img src="images/3.jpg" alt="" /></a></li>
<li><a href="#"><img src="images/4.jpg" alt="" /></a></li>
<li><a href="#"><img src="images/5.jpg" alt="" /></a></li>
<li><a href="#"><img src="images/6.jpg" alt="" /></a></li>
</ul>
</div>
<div class="slider-ctrl">
<span class="prev" id="prev"></span>
<span class="next" id="next"></span>
</div>
</div>
<script>
// 根据id获取元素
function $id(id) {
return document.getElementById(id);
}
// 返回指定dom节点的attr样式值
function getStyle(dom, attr) {
if (window.getComputedStyle) {
// 说明有getComputedStyle方法
return window.getComputedStyle(dom, null)[attr]
} else {
return dom.currentStyle[attr]
}
}
// 封装一个缓动的动画函数
function animate(dom, json, callback) {
/*
dom:要运动的节点
json:要运动的样式名
callback:运动完成的回调函数
*/
clearInterval(dom.timer);//要用定时器,先清定时器
//要运动的定时器
dom.timer = setInterval(function () {
var flag = true;
//json有几个属性,就要运动几次
for (var attr in json) {
//获取当前位置
var current = parseInt(getStyle(dom, attr));
// 计算速度
var speed = json[attr] - current > 0 ? Math.ceil((json[attr] - current) / 10) : Math.floor((json[attr] - current) / 10);
//计算下一个位置
var next = current + speed;
//定位元素
dom.style[attr] = next + 'px';
//判断是否达到目标
if (next != json[attr]) {
flag = false;
}
}
if (flag) {
clearInterval(dom.timer);
}
}, 20)// 每20毫秒
}
// 封装一个函数:第index个小圆点高亮
function light() {
// 所有都不高亮
for (var i = 0; i < imgArr.length; i++) {
spanArr[i].className = "slider-ctrl-con";
// 只有index高亮
spanArr[index].className = "slider-ctrl-con current";
}
}
// 把看下一张封装成一个函数
function autoplay() {
var next = index + 1;
if (next > imgArr.length - 1) {
next = 0;
}
// 当前要看的图的索引是index,马上要看的图的索引是next
// next是下一张,必须在右边
imgArr[next].style.left = width + "px";
// next来中间显示,index去左边
animate(imgArr[next], { left: 0 })
animate(imgArr[index], { left: -width })
// 更新当前显示的图片的索引
index = next;
// 点亮对应的小圆点
light()
}
// 获取元素
var sliderDiv = $id('slider'); //总容器
var imgArr = sliderDiv.children[0].children[0].children; //所有图片li集合
var prevBtn = $id('prev'); //上一张按钮
var nextBtn = $id('next'); //下一张按钮
var ctrlDiv = prevBtn.parentNode; //prevBtn的父节点,即控制按钮所在容器
// 定义一个变量,记录当前显示的是图片的索引/小圆点的索引
var index = 0; //索引最大长度为imgArr.length-1
// 定义一个变量,记录一个图片的宽度
var width = sliderDiv.offsetWidth;
// 中间:left:0
// 左边:left:-width
// 右边:left:width
// 1 根据图片的数量
/*
因为insertBefore是向前一一插入span小圆点的,
所以索引需要倒过来赋值才能得到正序索引
*/
for (var i = imgArr.length - 1; i >= 0; i--) {
// 生成相同的小圆点
var newPoint = document.createElement('span');
// 设置类名为slider-ctrl-con
newPoint.className = "slider-ctrl-con";
// innerHTML记录当前小圆点的索引
newPoint.innerHTML = i;
//将span小圆点放入slider-ctrl盒子中
ctrlDiv.insertBefore(newPoint, ctrlDiv.children[0]);
// 所有图片都去右边
imgArr[i].style.left = width + 'px';
}
// 获取所有控制按钮的集合
var spanArr = ctrlDiv.children; // 包括小圆点和左右箭头,但是小圆点在前面
// 2 第一个图片在中间
imgArr[index].style.left = 0;
light();
// 把小圆点和左右箭头的点击事件委托给ctrlDiv
ctrlDiv.onclick = function (e) {
e = window.event || e; //浏览器兼容写法
var target = e.target || e.srcElement; //浏览器兼容写法
if (target.className == 'prev') {
// 3 点击prev显示上一张图片,同时对应小圆点高亮
var next = index - 1;
if (next < 0) {//如果这已经是第一张了,则跳转到最后一张
next = imgArr.length - 1;
}
// 当前要看的图的索引是index,马上要看的图的索引是next
// next是上一张,必须在左边
imgArr[next].style.left = -width + "px";
// next来中间显示,index去右边
animate(imgArr[next], { left: 0 })
animate(imgArr[index], { left: width });
// 更新当前显示的图片的索引
index = next;
// 点亮对应的小圆点
light();
} else if (target.className == 'next') {
// 4 点击next显示下一张图片,同时对应小圆点高亮
autoplay();
} else if (target.className.indexOf('slider-ctrl-con') > -1) {
// 5 点击小圆点,切换到对应的图片,同时小圆点高亮
var next = parseInt(target.innerHTML); //要看的图片的索引,字符串,转数值
if (next > index) {
// 类似下一张,next在右边
imgArr[next].style.left = width + "px";
// next来中间显示,index去左边
animate(imgArr[next], { left: 0 })
animate(imgArr[index], { left: -width });
// 更新当前显示的图片的索引
index = next;
// 点亮对应的小圆点
light()
} else if (next < index) {
// 类似上一张,next在左边
imgArr[next].style.left = -width + "px";
// next来中间显示,index去右边
animate(imgArr[next], { left: 0 })
animate(imgArr[index], { left: width });
// 更新当前显示的图片的索引
index = next;
// 点亮对应的小圆点
light()
}
}
}
// 6 可以自动轮播
sliderDiv.timer = setInterval(autoplay, 3000);
// 7 鼠标移入slider盒子,停止轮播
sliderDiv.onmouseenter = function () {
clearInterval(sliderDiv.timer);
}
// 8 鼠标移出slider盒子,继续轮播
sliderDiv.onmouseleave = function () {
clearInterval(sliderDiv.timer);
sliderDiv.timer = setInterval(autoplay, 3000);
}
</script>
</body>
</html>
所用图片:
相关知识点
事件委托相关讲解链接:https://blog.csdn.net/qq_45677671/article/details/113184144
由于你们没有图片,直接复制代码,展示不出效果,大家可以自己找几张图片来代替,稍微修改下即可,只要能看得懂代码,修改起来莫得问题啦