轮播图也称为焦点图,是网页中比较常见的网页特效。

功能需求:

1.鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮。

2.点击右侧按钮一次,图片往左播放一张,以此类推,左侧按钮同理。

3.图片播放的同时,下面小圆圈模块跟随一起变化。

4.点击小圆圈,可以播放相应图片。

5.鼠标不经过轮播图,轮播图也会自动播放图片。

6.鼠标经过,轮播图模块, 自动播放停止。

window.addEventListener('load', function() {
    // 1. 获取元素
    var arrow_l = document.querySelector('.arrow_l')
    var arrow_r = document.querySelector('.arrow_r')
    var mainbox_l = document.querySelector('.mainbox_l')
    var mainbox_l_width = mainbox_l.offsetWidth;

    var num = 0;
    var circle = 0;
    // 定义节流阀
    var flag = true;
    // 2.给盒子添加事件:鼠标经过盒子,左右箭头盒子显示出来
    mainbox_l.addEventListener('mouseenter', function() {
            clearInterval(timer);
            // 清除定时器变量
            timer = null;
            arrow_l.style.display = 'block';
            arrow_r.style.display = 'block';
        })
        // 3.给盒子添加事件:鼠标离开盒子,左右箭头盒子隐藏
    mainbox_l.addEventListener('mouseleave', function() {
            arrow_l.style.display = 'none';
            arrow_r.style.display = 'none';
            timer = setInterval(function() {
                //手动调用点击事件
                arrow_r.click();
            }, 2000)

        })
        // 4.自动生成小圆圈circle
    var ul = mainbox_l.querySelector('ul')
    var ol = mainbox_l.querySelector('ol')
    for (var i = 0; i < ul.children.length; i++) {
        li = document.createElement('li');
        // 需要给li设置属性index后面方便调用
        li.setAttribute('index', i);
        ol.appendChild(li);
        // 给li鼠标设置一个经过,图片跳转的效果
        li.addEventListener('mouseenter', 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  
            num = index;
            // 当我们点击了某个小li 就要把这个li 的索引号给 circle  
            circle = index;
            // 5.实现ul图片移动效果
            animate(ul, -mainbox_l_width * index)
        })
    }
    // 给第一个小圆圈设置默认选中属性
    ol.children[0].className = 'current';
    // 6. 克隆第一张图片(li)放到ul 最后面,注意是深拷贝
    var first = ul.children[0].cloneNode(true);
    ul.appendChild(first);
    // 7. 点击右侧按钮, 图片滚动一张
    arrow_r.addEventListener('click', function() {
        if (flag) {
            flag = false; // 关闭节流阀
            // 如果走到了最后复制的一张图片,此时 我们的ul 要快速复原 left 改为 0
            if (num == ul.children.length - 1) {
                ul.style.left = 0;
                num = 0;
            }
            num++;
            animate(ul, -num * mainbox_l_width, function() {
                    flag = true;
                })
                // 8. 点击右侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放
            circle++;
            if (circle == ol.children.length) {
                circle = 0;
            }
            circlechange()
        }
    })

    // 左侧按钮做法:
    arrow_l.addEventListener('click', function() {
        if (flag) {
            flag = false;
            // 首先让图片滚动起来
            if (num == 0) {
                ul.style.left = (ul.children.length - 1) * mainbox_l_width;
                num = ul.children.length - 1;
            }
            num--;
            animate(ul, -num * mainbox_l_width, function() {
                flag = true;
            })
            circle--;
            circle = circle < 0 ? ol.children.length - 1 : circle;
            circlechange();
        }
    })
    var timer = this.setInterval(function() {
        arrow_r.click();
    }, 2000)

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

function animate(obj, target, callback) {
    // 需要先清除定时器,防止连续点击速度变快
    clearInterval(obj.timer)
    obj.timer = setInterval(function() {
        if (obj.offsetLeft == target) {
            // 当到达目标距离时,就要清除定时器
            clearInterval(obj.timer);
            callback && callback();
        } else {
            // 计算步长,每次移动距离慢慢变小,速度慢慢落下来.核心算法:(目标值-现在位置)/10
            var step = (target - obj.offsetLeft) / 10
            step = step > 0 ? Math.ceil(step) : Math.floor(step);
            // 注意需要添加else语句,直接写会导致点击时即使到达目标位置还会动
            obj.style.left = obj.offsetLeft + step + 'px';
        }
    }, 15)
}