【前端】手写轮播图·教程1

效果图:

在这里插入图片描述

在这里插入图片描述

需求分析:

  1. 根据图片的数量生成相同的小圆点,类名是slider-ctrl-con
  2. 显示第一个图片,同时第一个小圆点高亮,类名是:slider-ctrl-con current;
  3. 点击prev显示上一张图片,同时对应小圆点高亮
  4. 点击next显示下一张图片,同时对应小圆点高亮
  5. 点击小圆点,切换到对应的图片,同时小圆点高亮
  6. 可以自动轮播(每隔3000ms自动切换到下一张)
  7. 鼠标移入slider盒子,停止轮播
  8. 鼠标移出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部分
  1. 为了使代码简洁,先单独封装几个函数
<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>
  1. 主体部分,需要用到封装的函数调用即可
<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

由于你们没有图片,直接复制代码,展示不出效果,大家可以自己找几张图片来代替,稍微修改下即可,只要能看得懂代码,修改起来莫得问题啦

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一颗不甘坠落的流星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值