JS案例-网页轮播图

  1. 鼠标经过轮播图模块,左右按钮提示,离开隐藏左右按钮
  2. 点击右侧按钮一次,图片往左播放一张,以此类推,左侧按钮同理
  3. 图片播放的同时,下面小圆圈模块跟随一起变化
  4. 点击小圆圈,可以播放相应图片
  5. 鼠标不经过轮播图,轮播图也会自动播放图片
  6. 鼠标经过,轮播图模块自动播放停止

第一步 鼠标经过显示按钮 鼠标离开按钮消失

    //获取元素
    var arrow_l = document.querySelector('.arrow-l');
    var arrow_r = document.querySelector('.arrow-r');
    var focus = document.querySelector('.focus');
    //鼠标经过显示按钮
    focus.addEventListener('mouseenter', function () {
        arrow_l.style.display = 'block';
        arrow_r.style.display = 'block';
    })
    focus.addEventListener('mouseleave', function () {
        arrow_l.style.display = 'none';
        arrow_r.style.display = 'none';
    })

第二步:考虑如何动态生成小圆圈 让小圆圈个数与图片个数一致

首先得到ul里图片个数,利用循环动态生成小圆圈,创建节点并插入节点,然后给第一个小圆圈插入current类

    //动态生成小圆圈
    var ul = focus.querySelector('ul');//必须限定focus里面的
    var ol = focus.querySelector('.circle');
    for (var i = 0; i < ul.children.length; i++) {
        var li = document.createElement('li');
        ol.appendChild(li);
        //[]
    }
	ol.children[0].className = 'current';//第一个小圆圈默认变色

第三步:利用排他思想,实现点击小圆圈变色

        //可以直接在生成小圆圈的同时绑定点击事件
        li.addEventListener('click', function () {
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].className = '';
            }
            this.className = 'current';
        })

第四步:点击小圆圈滚动图片

注意是ul在移动

当点击某个小圆圈,就让图片滚动,移动距离为图片索引号*图片宽度

知识点:索引号如何得到?

  • 通过给每个li设定自定义属性点击时获取自定义属性
    var ul = focus.querySelector('ul');//必须限定focus里面的
    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';
            //点击小圆圈移动图片
            var index = this.getAttribute('index');
            var focusWidth = focus.offsetWidth;
            animate(ul, -index * focusWidth);
        })
    }

第五步:点击左右按钮滚动

思路:声明一个变量,每点击一次number++

但是当点击次数过多会走到空白区域

如何实现无缝滚动?

  • 把ul第一个li复制一份,放到ul后面,当图片滚动到克隆的最后一张的时候不做动画直接快速跳回第一张:left=0,同时num=0;

如何克隆第一张图片?

  • 利用节点的克隆和添加操作
    ol.children[0].className = 'current';//第一个小圆圈默认变色
    var firstLi = ul.children[0].cloneNode(true);
    ul.appendChild(firstLi);//克隆第一张图
    var num = 0;
    arrow_r.addEventListener('click', function () {
        if (num == ul.children.length - 1) {
            ul.style.left = 0;
            num = 0;
        }
        num++;
        animate(ul, -num * focusWidth);
    })

第六步:点击按钮小圆圈跟随变化

再定义一个变量circle,每次点击一次按钮则++,如果circle==4,说明走到最后这张图片,使circle复原

    var circle = 0;
    arrow_r.addEventListener('click', function () {
        if (num == ul.children.length - 1) {
            ul.style.left = 0;
            num = 0;
        }
        num++;
        animate(ul, -num * focusWidth);
        //实现点击按钮小圆圈跟随变化
        circle++;

        if (circle == ol.children.length) {
            circle = 0;
        }
        for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = '';
        }
        ol.children[circle].className = 'current';

第七步:此时有两个bug

按钮的点击操作和圆点的点击是不同变量,无法共同使用,两个事件的变量需要同步

应该在点击小圆点事件中添加

num = index;
circle = index;

第八步:左侧按钮同理

arrow_l.addEventListener('click', function () {
        if (num == 0) {
            num = ul.children.length - 1;
            ul.style.left = -num * focusWidth + 'px';
        }
        num--;
        animate(ul, -num * focusWidth);
        //实现点击按钮小圆圈跟随变化
        circle--;

        if (circle < 0) {
            circle = ol.children.length - 1;
        }
        for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = '';
        }
        ol.children[circle].className = 'current';
    })

第十步 代码优化 相同的可以封装函数

    function circleChange() {
        for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = '';
        }
        ol.children[circle].className = 'current';
    }

三元表达式简化

        circle = circle < 0 ? ol.children.length - 1 : circle;
        // if (circle < 0) {
        //     circle = ol.children.length - 1;
        // }

最后:自动播放!

发现自动播放时和点击右侧按钮很类似

可以手动调用右侧按钮点击事件arrow_r.click()

    focus.addEventListener('mouseenter', function () {
        arrow_l.style.display = 'block';
        arrow_r.style.display = 'block';
        clearInterval(timer);//鼠标经过停止定时器
        timer = none;
    })
    focus.addEventListener('mouseleave', function () {
        arrow_l.style.display = 'none';
        arrow_r.style.display = 'none';
        timer = setInterval(function () {//鼠标离开开启定时器
            arrow_r.click();//手动调用点击事件
        }, 2000)
    })

补充:节流阀

防止轮播图按钮连续点击造成播放过快

目的:当上一个函数动画执行完毕,再去执行下一个函数动画,让事件无法连续触发

利用回调函数,添加一个变量来控制,锁住函数和解锁函数

  • 开始设置一个变量var flag=true
  • if(flag) {flag=false;do something}关闭水龙头

利用回调函数 动画执行完毕(使用回调函数),false=true 打开水龙头

完整js代码

window.addEventListener('load', function () {
    //获取元素
    var arrow_l = document.querySelector('.arrow-l');
    var arrow_r = document.querySelector('.arrow-r');
    var focus = document.querySelector('.focus');
    var focusWidth = focus.offsetWidth;
    var num = 0;
    //鼠标经过显示按钮
    focus.addEventListener('mouseenter', function () {
        arrow_l.style.display = 'block';
        arrow_r.style.display = 'block';
        clearInterval(timer);//鼠标经过停止定时器
        timer = none;
    })
    focus.addEventListener('mouseleave', function () {
        arrow_l.style.display = 'none';
        arrow_r.style.display = 'none';
        timer = setInterval(function () {//鼠标离开开启定时器
            arrow_r.click();//手动调用点击事件
        }, 2000)
    })

    //动态生成小圆圈
    var ul = focus.querySelector('ul');//必须限定focus里面的
    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';
            //点击小圆圈移动图片
            var index = this.getAttribute('index');
            //当我们点击了某个li,就要把这个li的索引号给num//////////////////////////////bug必须改
            num = index;
            circle = index;
            animate(ul, -index * focusWidth);
        })
    }
    ol.children[0].className = 'current';//第一个小圆圈默认变色
    var firstLi = ul.children[0].cloneNode(true);
    ul.appendChild(firstLi);//克隆第一张图

    var circle = 0;//全局变量
    var flag = true;
    arrow_r.addEventListener('click', function () {
        if (flag) {
            flag = false;//关闭节流阀
            if (num == ul.children.length - 1) {
                ul.style.left = 0;
                num = 0;
            }
            num++;
            animate(ul, -num * focusWidth, function () {
                flag = true;//打开节流阀
            });
            //实现点击按钮小圆圈跟随变化
            circle++;

            if (circle == ol.children.length) {
                circle = 0;
            }
            circleChange();
        }

    })

    arrow_l.addEventListener('click', function () {
        if (flag) {
            flag = false;
            if (num == 0) {
                num = ul.children.length - 1;
                ul.style.left = -num * focusWidth + 'px';

            }
            num--;
            animate(ul, -num * focusWidth, function () {
                flag = true;
            });
            //实现点击按钮小圆圈跟随变化
            circle--;
            circle = circle < 0 ? ol.children.length - 1 : circle;
            // if (circle < 0) {
            //     circle = ol.children.length - 1;
            // }
            circleChange();
        }
    })
    function circleChange() {
        for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = '';
        }
        ol.children[circle].className = 'current';
    }
    var timer = setInterval(function () {
        arrow_r.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();//借助短路运算如果有参数传入才会调用callback
        }
        // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
        obj.style.left = obj.offsetLeft + step + 'px';

    }, 15);
}

相关html

<div class="focus">
                <a href="javascript:;" class="arrow-l">&lt;</a>
                <a href="javascript:;" class="arrow-r">&gt;</a>
                <ul>
                    <li><a href="#"><img src="upload/focus1.png" alt=""></a></li>
                    <li><a href="#"><img src="upload/focus1.jpg" alt=""></a></li>
                    <li><a href="#"><img src="upload/focus2.jpg" alt=""></a></li>
                    <li><a href="#"><img src="upload/focus3.jpg" alt=""></a></li>

                </ul>
                <ol class="circle">

                </ol>

相关css

.focus {
    float: left;
    overflow: hidden;
    position: relative;
    width: 721px;
    height: 455px;

}

.arrow-l,.arrow-r {
    display: none;
    position: absolute;
    top: 50%;
    margin-top: -20px;
    width: 24px;
    height: 40px;
    color:rgb(175, 170, 170);
    font-size: 20px;
    line-height: 40px;
    text-align: center;
    z-index: 10;
    background:rgba(0,0,0, .5);

}
.arrow-l {
    left: 0;
    border-radius: 0 30px 30px 0;
    
}
.arrow-r {
    right: 0;
    border-radius: 30px 0 0 30px;
    
}
.focus ul{
    position: absolute;
    top: 0;
    left: 0;
    width: 600%;
}
.focus ul li{
    float: left;
}
.circle{
    position: absolute;
    bottom: 0;
    left: 40px;
    bottom: 0;
    height: 18px;
    width: 150px;
    

}
.circle li{
    height: 12px;
    width: 12px;
    float: left;
    border-radius: 8px;
    border: 1px solid #e4e4e4;
    margin: 0 4px;
}
.current {
    background-color:  #e4e4e4;
}
posted @ 2021-11-13 16:50  清梨  阅读(181)  评论(0编辑  收藏  举报