效果粗略演示:


当鼠标经过图片时左右两侧的箭头才显示,且图片停止轮播;当鼠标点击箭头或小圆点时会跳到相对应的图片;当鼠标离开后图片继续无限循环播放

Animation_1.gif

核心原理:


在一个大的div父盒子里放一个ul,ul里有若干个li(用浮动让li排成一行),每个li里面放一张图片,再封装一个动画函数让ul在水平方向移动,同时用overflow:hidden将溢出父盒子的部分隐藏起来
在设置li的浮动时,先给ul一个较大的宽度(ul的宽度会溢出父盒子),否则浮动的li会掉下来无法排成一行

QQ图片20200329224343.png

基本HTML结构:


<div class="father">
        <img class="arrow_l" src="images/arrow_l.png" alt="">
        <img class="arrow_r" src="images/arrow_r.png" alt="">
        <ul>
            <li>
                <img src="images/img_1.jpg" alt="">
            </li>
            <li>
                <img src="images/img_2.jpg" alt="">
            </li>
            <li>
                <img src="images/img_3.jpg" alt="">
            </li>
            <li>
                <img src="images/img_4.jpg" alt="">
            </li>
            <li>
                <img src="images/img_5.jpg" alt="">
            </li>
        </ul>
        <!-- 左下角的小圆点,但现在还不确定有几个小圆点 -->
        <ol class="circle">

        </ol>
    </div>

封装动画函数


函数的参数分别为调用者,目标位置,回调函数(如果有回调函数就执行,没有就不执行),调用者从原位置移动到目标位置就停止
这里运用了缓动动画效果,即运动速度刚开始较快,然后逐渐变慢,直到停止(不用缓动效果的话,整个运动过程就会显得较为生硬)

// 封装动画函数animate
    function animate(obj, target, back) {
        var timer = setInterval(function() {
            if (obj.offsetLeft == target) {
                clearInterval(timer);
                if (back) {
                    back();
                }
            }
            var everyStep = (target - obj.offsetLeft) / 10;
            everyStep = everyStep > 0 ? Math.ceil(everyStep) : Math.floor(everyStep);
            obj.style.left = obj.offsetLeft + everyStep + 'px';
        }, 15);
    }

图片的滑动


利用封装好的动画函数animate( ul , - fatherWidth * num )即可实现,调用对象是ul,fatherWidth是父盒子的宽度,num为当前显示的图片的索引号,fatherWidth和num的乘积就是整个ul要移动的距离

Animation_9.gif

左右两侧箭头


等鼠标经过父盒子时箭头显现,轮播暂定
鼠标离开父盒子时箭头消失,重新开始轮播

.arrow_l,
.arrow_r {
    position: absolute;
    display: none;
    /* ul和箭头都定位了,箭头被压在了下面,要提上来 */
    z-index: 2;
}
  // 给父盒子注册鼠标进入事件,鼠标进入时箭头显现,同时控制图片播放的定时器停止
    father.addEventListener('mouseenter', function() {
            arrow_l.style.display = 'block';
            arrow_r.style.display = 'block';
            clearInterval(timer_1);
            timer_1 = null;
        })
 // 给父盒子注册鼠标离开事件
    father.addEventListener('mouseleave', function() {
            arrow_l.style.display = 'none';
            arrow_r.style.display = 'none';
            timer_1 = setInterval(function() {
                arrow_r.click();
            }, 2000);
        })

Animation.gif

小圆点:


这里有个问题,就是小圆点的个数应该是和图片的张数是一致的,所以我们不能直接定义小圆点的个数,而应该让圆点个数随着图片张数的变化而变化(顺便在循环中为小圆点注册鼠标点击事件)
在js中定义变量current_index,表示当前小圆点的索引号
当鼠标点击小圆点时,当前图片的索引号和小圆点的索引号是相同的

 for (var i = 0; i < ul.children.length; i++) {
        var li = document.createElement('li');
        ol.appendChild(li);
        li.setAttribute('index', i);
        // 默认第一个小圆圈的颜色为白色
        ol.children[0].className = 'current_color';
        // 顺便为小圆点注册事件
        li.addEventListener('click', function() {
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].className = '';
            }
            this.className = 'current_color';
            var current_index = this.getAttribute('index');
            num = current_index;
            circle = current_index;
            animate(ul, -current_index * father_Width);

        })
    }

Animation_8.gif

左箭头控制图片向右移动


// 每次点击左箭头时,图片向右轮播
    arrow_l.addEventListener('click', function() {
        if (flag) {
            flag = false;
            if (num == 0) {
                num = ul.children.length - 1;
                // 一定要加px,否则最左图片切换到最右图片时不连贯
                ul.style.left = -num * father_Width + 'px';
            }
            num--;
            animate(ul, -num * father_Width, function() {
                flag = true;
            });
            circle--;
            circle = circle < 0 ? ol.children.length - 1 : circle;
            circleChange();
        }
    })

Animation_7.gif

右箭头控制图片向左移动


// 每次点击右箭头时,图片向左轮播
    arrow_r.addEventListener('click', function() {
            if (flag) {
                flag = false;
                if (num == ul.children.length - 1) {
                    num = 0;
                    ul.style.left = 0;
                }
                num++;
                animate(ul, -num * father_Width, function() {
                    flag = true;
                });
                circle++;
                if (circle == ol.children.length) {
                    circle = 0;
                }
                circleChange();
            }

        })

Animation_10.gif

小技巧


为了使第5张图片和第1张图片之间的过渡显得更加连贯自然,在第6张图片的位置加了一张图片(和第1张图片一模一样)

播放的当前图片为最后一张图片时(即为第6张时),利用定位迅速让当前图片变成第1张

if (num == ul.children.length - 1) {
                    num = 0;
                    ul.style.left = 0;
                }

Animation_11.gif

如果要使鼠标点击左箭头让当前图片从第1张切换到第5张,那么在当前图片为第1张的时候,利用定位迅速让当前图片变成第6张

if (num == 0) {
                num = ul.children.length - 1;
                ul.style.left = -num * father_Width + 'px';
            }

Animation_12.gif

注意:上面的定位一定要加单位px,否则就会出现下面这种过渡不连贯的效果

Animation_2.gif

图片自动轮播


var timer_1 = setInterval(function() {
        arrow_r.click();
    }, 1500);

附:湖人总冠军!!!


null
4 声望0 粉丝