手写网页端轮播图(简易版)

496 阅读2分钟
轮播图是网站最常见特效之一,了解底层原理,非常有必要

js实现思路:
1.先获取到需要操作的dom元素
2.鼠标经过离开事件>移入box中显示左右箭头,移出隐藏左右箭头
3.图片轮播到最后一张需要第一张图片来过渡一下,所以就需要动态克隆第一张图片追加到ul
4.动态添加小圆点,并动态设置图片的自定义属性 data-index
5.获取所有小圆点,并动态添加显示current样式,排它显示小圆点
6.通过click事件绑定到小圆点上,通过li图片的data-index属性和盒子的宽度进行相乘达到切换图片位置的目的,注意,ul必须定位,否则没有效果。
7.设置左右按钮切换图片,先定义一个全局变量num,同上,让其和盒子宽度相乘,变量num小于等于li的长度减1
8.设置定时器自动轮播图片,当鼠标移入box设置鼠标移入停止这个定时器。此时到这你的录播图基本可以动起来了,最后我还写了一个缓动动画的函数,让轮播看起来更唯美,不生硬。

HTML结构模块:

注:常见的轮播图至少三层结构:外面一个大盒子,中间ul套li

    <!-- 大盒子 -->
    <div class="box">
        <ul>
            <li><img src="./05-轮播图制作/upload/focus.jpg" alt=""></li>
            <li><img src="./05-轮播图制作/upload/focus1.jpg" alt=""></li>
            <li><img src="./05-轮播图制作/upload/focus2.jpg" alt=""></li>
            <li><img src="./05-轮播图制作/upload/focus3.jpg" alt=""></li>
        </ul>
        <!-- 左箭头 -->
        <a href="javascript:;" class="prev">
            < </a>
                <!-- 右箭头 -->
                <a href="javascript:;" class="next"> > </a>
                <ol class="circle">
                </ol>
    </div>

css样式模块

<style>
    * {
        margin: 0;
        padding: 0;
        list-style: none;
    }

    a {
        text-decoration: none;
        color: #fff;
        font-size: 30px;
    }

    .box {
        position: relative;
        margin: 0 auto;
        width: 721px;
        height: 455px;
        background-color: skyblue;
        overflow: hidden;
    }

    .box ul {
        position: absolute;
        width: 500%;
    }

    .box ul li {
        float: left;
    }


    .box .prev {
        position: absolute;
        top: 50%;
        left: 0;
        width: 40px;
        height: 70px;
        transform: translateY(-50%);
        text-align: center;
        line-height: 60px;
    }

    .box .next {
        position: absolute;
        top: 50%;
        right: 0;
        width: 40px;
        height: 70px;
        transform: translateY(-50%);
        text-align: center;
        line-height: 60px;
    }

    .next,
    .prev {
        display: none;
        background-image: linear-gradient(transparent,
                rgba(0, 0, 0, .3));
    }

    ol li {
        width: 8px;
        height: 8px;
        border-radius: 50%;
        border: 2px solid #fff;
        float: left;
        margin-right: 5px;
        cursor: pointer;
    }

    .circle {
        position: absolute;
        bottom: 20px;
        left: 50%;
        transform: translateX(-50%);
    }

    .current {
        background-color: #fff;
    }
</style>
<script>
        // 上一张图片按钮
        var prev = document.querySelector('.prev')
        // 下一张图片按钮
        var next = prev.nextElementSibling
        var box = document.querySelector('.box')
        var ul = box.children[0]
        var circle = document.querySelector('.circle')

        // 鼠标移入显示左右箭头
        box.addEventListener('mouseenter', function () {
            prev.style.display = 'block'
            next.style.display = 'block'
            clearInterval(timer)
        })

        // 鼠标移出隐藏左右箭头
        box.addEventListener('mouseleave', function () {
            prev.style.display = 'none'
            next.style.display = 'none'
            timer = setInterval(function () {
                next.click();
            }, 3000)
        })

        // 克隆第一张到最后面
        cloneli = ul.children[0].cloneNode(true)
        ul.appendChild(cloneli)
        var lis = ul.querySelectorAll('li')
        // 动态添加小圆点的li
        for (var i = 0; i < lis.length - 1; i++) {
            var li = document.createElement('li');
            circle.appendChild(li)
            // 动态设置图片的自定义属性 data-index
            lis[i].setAttribute('data-index', i)
        }
        // 给第一个默认显示current样式
        circle.children[0].classList.add('current')


        // 获取所有小圆点li
        var cirlis = circle.querySelectorAll('li')

        // 排它显示小圆点
        for (let i = 0; i < cirlis.length; i++) {
            cirlis[i].addEventListener('click', function () {
                setCir(cirlis)
                this.classList.add('current')
            })
        }
        for (let i = 0; i < cirlis.length; i++) {
            // 点击小圆圈切换图片
            cirlis[i].addEventListener('click', function () {
                //  获取图片li的data-index
                var cirIndex = lis[i].getAttribute('data-index')
                animate(ul, -lis[i].offsetWidth * cirIndex)
            })
        }
        var num = 0;
        var cires = 0;
        var flag = true;
        next.addEventListener('click', function () {
            if (flag) {
                flag = false
                cires++;
                if (num == lis.length - 1) {
                    num = 0
                    ul.style.left = 0
                }
                num++
                animate(ul, -lis[0].offsetWidth * num, function () {
                    flag = true
                })
                if (cires == lis.length - 1) {
                    cires = 0
                }
                setCir(cirlis)
                cirlis[cires].classList.add('current')
            }
        })

        prev.addEventListener('click', function () {
            if (flag) {
                flag = false
                if (num == 0) {
                    num = lis.length - 1
                    ul.style.left = -num * lis[0].offsetWidth + 'px'
                }
                num--
                animate(ul, -lis[0].offsetWidth * num, function () {
                    flag = true
                })
                cires--;
                setCir(cirlis)
                cires = cires < 0 ? cirlis.length - 1 : cires
                cirlis[cires].classList.add('current')
            }
        })

        // 封装排它函数 清除所有小圆点属性
        function setCir(cir) {
            for (var i = 0; i < cir.length; i++) {
                cir[i].classList.remove('current')
            }
        }
        // 自动播放轮播图
        var timer = setInterval(function () {
            next.click();
        }, 3000)
    </script>
//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);
}

-------end