轮播图,作为前端学习的经典案例,涉及了各种知识点,包括动画函数,js基础知识以及逻辑思路等,一辈子只做一次。
下面总结实现轮播图的三种方法,从易到难,大家选择性学习。

一、 Vue.js实现轮播图

源码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title></title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <style type="text/css">
            #mask{
                margin: 0px auto;
                width: 690px;      /*盒子宽度和高度跟图片一致 */
                height: 380px;
            }
            .left,.right{
                width: 50px;
                height: 50px;
            }
            .left{
                position: relative;
                top: -250px;
            }
            .right{
                position: relative;
                top: -250px;
                left: 300px;
                float: left;
            }
        </style>
    </head>
    <body>
        <div id="mask">
            <!-- 鼠标经过时自动播放图片 -->
           <img :src="imgArr[index]"v-on:mouseover="change" v-on:mouseout="stop">
        </div>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script>
            var app=new Vue({
                el: '#mask',
                data: {
                    imgArr:[
                        "./image/lx1.jpeg",
                         "./image/lx2.jpeg",
                         "./image/lx3.jpeg",
                         "./image/lx4.jpeg",
                    ],
                    index:0

                },
                methods:{
                    next:function (){

                        this.index++;
                        if(this.index===4){
                            this.index=0
                        }
                    },
                    change:function(){
                    this.timer=setInterval(this.next,2000);
                    },
                    stop:function (){
                        clearInterval(this.timer)
                    }
				},
            })
        </script>
    </body>
</html>

二、js+css实现轮播图(移动端)

index.html

<!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>
    <link rel="stylesheet" href="./css/index.css">
    <script src="./js/index.js"></script>
</head>
<body>
    <div class="focus">
        <ul>
            <li>
                <a href="#"><img src="./img/lx1 (3).jpeg" alt=""></a>
            </li>
            <li>
                <a href="#"><img src="./img/lx1 (1).jpg" alt=""></a>
            </li>
            <li>
                <a href="#"><img src="./img/lx1 (2).jpeg" alt=""></a>
            </li>
            <li>
                <a href="#"><img src="./img/lx1 (3).jpeg" alt=""></a>
            </li>
            <li>
                <a href="#"><img src="./img/lx1 (1).jpg" alt=""></a>
            </li>
        </ul>
        <ol class="circle">
            <li class="current"></li>
            <li></li>
            <li></li>
        </ol>
    </div>
</body>
</html>

img

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

css

index.css

*{
    margin: 0%;
    padding: 0%;
}
.focus {
    margin: 0px auto;
    position: relative;
    width: 690px;
    height: 350px;
    background-color: #fff;
    overflow: hidden;
}
.focus ul {
    position: absolute;
    top: 0;
    left: 0;
    width: 500%;
    margin-left: -100%;
}

.focus ul li {
    float: left;
    width: 20%;
}
.circle {
    position: absolute;
    bottom: 10px;
    right: 50px;
}
.circle li {
    list-style: none;
    float: left;
    width: 8px;
    height: 8px;
    /* background-color: #fff; */
    border: 2px solid rgba(255, 255, 255, 0.5);
    margin: 0 3px;
    border-radius: 50%;
    /*鼠标经过显示小手*/
    cursor: pointer;
    transition: all .3s;
}
.focus ol li.current{
    width: 15px;
    background-color: #fff;
}

js

index.js


window.addEventListener('load',function(){
    var focus=document.querySelector('.focus')
    var ul=focus.children[0]
    var ol=focus.children[1]
    var focusWidth=focus.offsetWidth
    var index=0
    var timer=setInterval(function(){
        index++
        // 移动距离
        var step=-index*focusWidth
        ul.style.transition='all .3s'
        ul.style.transform='translateX('+step+'px)'
    },2000);
    //判断过渡是否完成
    ul.addEventListener('transitionend',function(){
        //如果到达第三张图片,将无缝跳转到第一张
        if(index>=ul.children.length-2){
            index=0
            ul.style.transition='none'
            var step=-index*focusWidth
            ul.style.transform='translateX('+step+'px)'
        }
        else if(index<0){
            index=ul.children.length-3//跳转到第三张图片
            ul.style.transition='none'
            var step=-index*focusWidth
            ul.style.transform='translateX('+step+'px)'
        }
        //小圆点跟随变化
        ol.querySelector('.current').classList.remove('current')
        ol.children[index].classList.add('current')
    })
    //手指拖动图片
    // 初始位置
    var startX=0
    var moveX=0
    var flag=false
    ul.addEventListener('touchstart', function (e) {
        // 获取鼠标位置
        startX = e.targetTouches[0].pageX
        clearInterval(timer)
        
    })
    ul.addEventListener('touchmove', function (e) {
        moveX = e.targetTouches[0].pageX-startX
        // 盒子位置=初始位置+盒子移动距离
        var step=-index*focusWidth+moveX
        ul.style.transition='none'
        ul.style.transform='translateX('+step+'px)'
        flag=true //触发移动事件,flag为true 
    })
    //手指左右滑动切换图片
    ul.addEventListener('touchend',function(){
        if(flag){
            if(Math.abs(moveX)>50){
                //右滑上一张,当位于第一张图片是,index<0
                if(moveX>0){
                    index--
                }else{
                    index++  //左滑下一张
                }
                var step=-index*focusWidth
                ul.style.transition='all .3s'
                ul.style.transform='translateX('+step+'px)' 
            }else{
                var step=-index*focusWidth
                ul.style.transition='all .1s'
                ul.style.transform='translateX('+step+'px)'
            }
        }
        // 左右互动距离大于50,就切换上/或下一张图片
        clearInterval(timer)
        timer=setInterval(function(){
            index++
            // 移动距离
            var step=-index*focusWidth
            ul.style.transition='all .3s'
            ul.style.transform='translateX('+step+'px)'
        },2000);
        
    })
})

三、纯js实现轮播图(动画函数)

index.html

<!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>
    <link rel="stylesheet" href="./css/index.css">
    <script src="./js/animate.js"></script><!-- 需要位于index.js之上 -->
    <script src="./js/index.js"></script>
</head>

<body>
    <div class="main">
        <h1>轮播图</h1>
        <div class="focus">
            <a href="javascript:;" class="left">&lt;</a>
            <a href="javascript:;" class="right">&gt;</a>
            <ul>
                <li>
                    <a href="#"><img src="./img/lx1 (1).jpg" alt=""></a>
                </li>
                <li>
                    <a href="#"><img src="./img/lx1 (2).jpeg" alt=""></a>
                </li>
                <li>
                    <a href="#"><img src="./img/lx1 (3).jpeg" alt=""></a>
                </li>
                <li>
                    <a href="#"><img src="./img/lx1 (4).jpeg" alt=""></a>
                </li>
            </ul>
            <ol class="circle">
                
            </ol>
        </div>
    </div>
    
</body>

</html>

css

index.css

*{
    margin: 0%;
    padding: 0%;
}
.main{
    width: 690px;
    height: 350px;
    margin: 0px auto;
}
h1{
    text-align: center;
}
.focus {

    position: relative;
    width: 690px;
    height: 350px;
    background-color: purple;
    overflow: hidden;
}
.left,.right{
    display: none;
    position: absolute;
    top: 50%;
    margin-top: -20px;
    width: 24px;
    height: 40px;
    background: rgba(0, 0, 0, .3);
    text-align: center;
    line-height: 40px;
    color: #fff;
    font-family: 'icomoon';
    font-size: 18px;
    z-index: 2;
}
a{
    text-decoration: none;
}
.right{
    right: 0%;
}
.focus ul {
    position: absolute;
    top: 0;
    left: 0;
    width: 600%;
}

.focus ul li {
    float: left;
}
.circle {
    position: absolute;
    bottom: 10px;
    left: 50px;
}
.circle li {
    list-style: none;
    float: left;
    width: 8px;
    height: 8px;
    /*background-color: #fff;*/
    border: 2px solid rgba(255, 255, 255, 0.5);
    margin: 0 3px;
    border-radius: 50%;
    /*鼠标经过显示小手*/
    cursor: pointer;
}
.current{
    background-color: #fff;
}

img

同上

js

index.js


window.addEventListener('load',function(){
    var focus = document.querySelector('.focus')
    var left=document.querySelector('.left')
    var right=document.querySelector('.right')
    // 显示切换栏
    focus.addEventListener('mouseenter',function(){
        left.style.display='block'
        right.style.display='block'
    })
    // 隐藏切换栏
    focus.addEventListener('mouseleave',function(){
        left.style.display='none'
        right.style.display='none'
    })
    // 动态创建小圆圈  
    var focusWidth=focus.offsetWidth 
    var ul=focus.querySelector('ul')
    var ol = focus.querySelector('.circle')
    for(var i=0;i<ul.children.length;i++){
        var li=document.createElement('li')
        li.setAttribute('index', i);
        ol.appendChild(li)
        li.addEventListener('click',function(){
            for(var i=0;i<ol.children.length;i++){
                ol.children[i].className=''
            }
            this.className='current'
            // 当我们点击了某个小li 就拿到当前小li 的索引号
            var index = this.getAttribute('index');
            // 当我们点击了某个小li 就要把这个li 的索引号给 num  
            num = index;
            // 当我们点击了某个小li 就要把这个li 的索引号给 circle  
            circle = index;
            animate(ul, -index * focusWidth);
        })
        
    }
    ol.children[0].className='current'
    // 克隆第一张图片
    var first=ul.children[0].cloneNode(true)
    ul.appendChild(first)
    //图片指针
    var num=0
    // 圆圈指针
    var circle=0
    // flag 节流阀
    var flag=true
    //右侧按钮
    
    // console.log(foucusWidth);
    right.addEventListener('click',function(){
        if(flag){
            flag=false
            if(num==ul.children.length-1){
                ul.style.left=0
                num=0
            }
            num++
            var step=-num*focusWidth
            animate(ul,step,function(){
                flag=true //执行了animate函数后才能切换下一张图片
            })
            circle++
            if(circle==ol.children.length){
                console.log(ol.children.length);
                circle=0
            }
            circleChange();
        }
        
    })
    //左侧按钮
       
    left.addEventListener('click', function() {
        if (flag) {
            flag = false;
            if (num == 0) {
                num = ul.children.length - 1;
                ul.style.left = step + 'px';

            }
            num--;
            var step=-num*focusWidth
            animate(ul, step, function() {
                flag = true;
            });
            // 点击左侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放
            circle--;
            // 如果circle < 0  说明第一张图片,则小圆圈要改为第4个小圆圈(3)
            // if (circle < 0) {
            //     circle = ol.children.length - 1;
            // }
            circle = circle < 0 ? ol.children.length - 1 : circle;
            // 调用函数
            circleChange();
        }
    });
    function circleChange() {
        // 先清除其余小圆圈的current类名
        for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = '';
        }
        // 留下当前的小圆圈的current类名
        ol.children[circle].className = 'current'
    }
    // 10. 自动播放轮播图
    var timer = setInterval(function() {
        //手动调用点击事件
        right.click();
    }, 2000);
})

animate.js

//动画函数封装,实现匀减速移动图片
function animate(obj, target, callback) {
    // console.log(callback);  callback = function() {}  调用的时候 callback()

    // 先清除以前的定时器,只保留当前的一个定时器执行
    clearInterval(obj.timer);
    obj.timer = setInterval(function() {
        // 步长值写到定时器的里面
        // 把我们步长值改为整数 不要出现小数的问题
        // var step = Math.ceil((target - obj.offsetLeft) / 10);
        var step = (target - obj.offsetLeft) / 10;
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
        if (obj.offsetLeft == target) {
            // 停止动画 本质是停止定时器
            clearInterval(obj.timer);
            // 回调函数写到定时器结束里面
            // if (callback) {
            //     // 调用函数
            //     callback();
            // }
            callback && callback();
        }
        // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
        obj.style.left = obj.offsetLeft + step + 'px';

    }, 15);
}
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐