纯JS实现轮播图

写在前面 

是的,这个轮播图我看了一天的时间,网上找说明,外加请教别人,自己动手试着写写,昨天看了一下午,夜里又简单想了一下整个流程。终于今天上午开始动手写,磕磕绊绊,跌跌撞撞,完整的轮播让我给实现了。

总的来说,算是完成了,为啥要说算是呢,因为自己在独立地写的过程中还是会出现一些问题,就会看别人怎么写的,怎么实现的,再去对比一下自己的思路。遇到问题,思考问题,再到解决问题,是个需要不断重复的过程,只有这样,才会让自己熟练,时间长了,再遇到问题知道如何解决,从哪些地方去检查。

emmmmmmm,简单的学习心得分享完毕,开始撸思路,撸代码吧。

轮播图

轮播图功能需求:

 1. 鼠标经过/离开轮播图时  左右按钮的显示/隐藏

 2. 点击圆点时,圆度变为当前状态;图片切换

 3. 左右按钮点击时,轮播图片

 4. 图片轮播时 下方的圆点也跟着切换

 5. 鼠标放上焦点图时 图片停止自动轮播  ; 鼠标离开时 图片自动轮播

 需要注意的是,页面一开始图片就是轮播着的

优化的地方:

1. 增加节流阀:

当连续点击按钮时,一张图片没有轮播完就会出现下一张。增加的节流阀的目的就是解决上面所叙述的问题。一般节流阀就是两种操作,关闭节流阀(锁函数),打开节流阀(开函数)。

2. 提取代码相同的部分,单独作为一个函数,进行调用。还有就是把一些简单的if语句的判断可以使用三元表达式来代替

无缝轮播的思想

无缝轮播的布局:把放轮播图的ul中的第一个孩子li,复制一份放到ul的最后。

轮播具体实现的过程:正常的话,用户点击按钮进行图片的轮播,当用户看到最后一张图片(其实是我们布局中的倒数第二张)时,点击右侧按钮的时候,用户看到的是第一张图片,其本质是用户看到了我们布局中的最后一张,因为这一张图是我们复制的第一张图,与此同时,我们悄悄的把ul瞬间回到原位置(left = 0),制造假象,让用户以为是第一张图片,其实是我们布局中的最后一张。当用户再点击时,因为此时ul已经瞬间移回到原来的位置,再点击向右轮播的按钮,ul就按照正常的轮播到第二张图片。这样就实现了无缝轮播。

这是轮播图中比较重要的一个思想。思路解决了 ,咱们就看代码吧。

代码里面有很详细的解释,可以认真看看的。

JS部分

// 轮播图的需求:
// 1. 鼠标经过/离开轮播图时  左右按钮的显示/隐藏
// 2. 点击圆点时,圆度变为当前状态;图片切换
// 3. 左右按钮点击时,轮播图片
// 4. 图片轮播时 下方的圆点也跟着切换
// 5. 鼠标放上焦点图时 图片停止自动轮播  ; 鼠标离开时 图片自动轮播
// 需要注意的是,页面一开始图片就是轮播着的
window.addEventListener('load', function () {

    // 1. 鼠标经过轮播图时 按钮的显示和隐藏
    // 获取事件源
    var focus = document.querySelector('.focus');
    var arrowL = document.querySelector('.arrow-l');
    var arrowR = document.querySelector('.arrow-r');
    var ol = document.querySelector('.circle');
    var ul = focus.querySelector('ul');
    var focusWidth = focus.offsetWidth;
    focus.addEventListener('mouseenter', function () {
        arrowL.style.display = 'block';
        arrowR.style.display = 'block';
        clearInterval(carousel);
        carousel = null;
    })
    focus.addEventListener('mouseleave', function () {
        arrowL.style.display = 'none';
        arrowR.style.display = 'none';
        // 鼠标离开 自动轮播
        carousel = setInterval(function () {
            arrowR.click();
        }, 3000)
    })
    // 2.点击圆点部分
    // 圆点的个数应该是与图片的个数是一致的,所以 应该根据ul中的li的个数动态创建圆点的个数
    // js需要写的具有一定的动态性 改变结构 时 js可以动态生成
    for (var i = 0; i < ul.children.length; i++) {
        // (1)创建圆点 
        var li = document.createElement('li');
        // (2)添加到ol中
        ol.appendChild(li);
        // 设置一个变量 用来记录当前圆点的索引号 后面与图片位置对应显示
        li.setAttribute('index', i);
        // (3).点击圆点的事件效果 应该在创建之后就绑定事件
        li.addEventListener('click', function () {
            // (4).被点击的圆点 变成当前状态
            // 干掉所有人 ol.children.length所有小圆点的个数
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].className = '';
            }
            // 留下我自己 当前点击的圆点
            this.className = 'current';

            // (5). 点击时图片轮播
            // 获得当前圆点的索引号
            var currentIndex = this.getAttribute('index');
            // 轮播到哪个li 把当前图片对应的圆点的索引号 给点击的次数
            // 是保持圆点 按钮点击次数 图片对应一致
            clickCount = currentIndex;
            circleMove = currentIndex;

            // ul移动的距离  圆点索引号*焦点图的宽度
            animate(ul, -currentIndex * focusWidth);

        })
    }

    // 默认设置第一个圆点为当前
    ol.children[0].className = 'current';
    // 无缝轮播:把ul中的图片复制一份到ul的最后。当用户点击到最后一张,就是我们的倒数第二张
    // 用户再点击时 看到的是第一张的图片 其实是我们复制了第一张到ul的最后,所以用户看到的实际上是我们复制的那一张图
    // 这时当用户再点击时  我们迅速把ul移回原位left=0,从头开始 再按照正常的轮播到第二张


    // 克隆节点在创建小圆点的后面 因为克隆出来的节点不需要小圆点
    // 复制ul第一个li放到最后 ul.children[0].cloneNode(true)深拷贝
    var firstImg = ul.children[0].cloneNode(true);
    ul.appendChild(firstImg);
    // 点击按钮事件
    // 点击右侧按钮 图片向左轮播 点击一次 图片(ul)移动一个图片的距离
    // ul移动的距离 = 点击次数*焦点图的宽度  与上面点小圆点的效果类似
    // 设置一个变量记录 点击的次数  点击一次图片滚动一次
    var clickCount = 0;
    // 记录圆点的位置 控制圆点的播放
    var circleMove = 0;
    // 节流阈值:为了防止点击过快图片没有轮播完就结束的情况
    var flag = true;
    // 3.右侧按钮点击
    arrowR.addEventListener('click', function () {
        if (flag) {
            // 先锁住函数 当动画执行完毕之后 再解锁
            flag = false; // 关闭节流阀
            // (1) 当ul走到最后 我们复制的那一张图片时:ul的left = 0;迅速复原ul
            if (clickCount == ul.children.length - 1) {
                ul.style.left = 0;
                clickCount = 0; // 点击置0
            }

            clickCount++;
            animate(ul, -clickCount * focusWidth, function () {
                flag = true; // 打开节流阀
            });

            // (2) 图片轮播时 圆点也在变化
            circleMove++;
            // 当圆点到最后一个4 也就是图片轮播到我们复制的哪一个图片时  圆点从头开始
            if (circleMove == ol.children.length) {
                circleMove = 0
            }
            // circleMove == ol.children.length - 1 ? 0 : circleMove;
            // 调用函数 排他思想
            circleVisible();
        }


    })

    // 4.左侧按钮点击
    arrowL.addEventListener('click', function () {
        if (flag) {
            flag = false;
            // (1) 当ul是第一张图片时 点击时应轮播到倒数第二张 
            if (clickCount == 0) {
                ul.style.left = -clickCount * focusWidth + 'px';
                clickCount = ul.children.length - 1; // 点击数也回到图片对应的点击数
            }
            clickCount--;
            animate(ul, -clickCount * focusWidth, function () {
                flag = true;
            });

            // (2) 图片轮播时 圆点也在变化
            circleMove--;
            // 点击时 如果 circleMove < 0 说明是第一张图片 小圆点要从第4个开始 (索引号3)
            if (circleMove < 0) {
                circleMove = ol.children.length - 1
            }
            // circleMove < 0 ? ol.children.length - 1 : circleMove;
            // 调用函数 排他思想
            circleVisible();
        }
    })

    // 5.鼠标经过时  设置定时器 自动轮播图片
    // 自动轮播的效果 与点击右侧按钮的效果一样
    // 即可以使用手动调取 右侧按钮点击事件
    var carousel = setInterval(function autoCarousel() {
        arrowR.click();
    }, 3000)

    // 排他
    function circleVisible() {
        // 干掉所有人
        for (var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = '';
        }
        // 留下自己
        ol.children[circleMove].className = 'current';
    }

})

 

结构部分

这里有需要注意的一点,轮播图用到了之前封装的动画函数,需要引入动画的js文件,动画的js文件要在页面的js文件之前引入,因为动画js是依赖于页面的js文件的。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./css/lb.css">
    <!-- 依赖于lb.js 因为只有在有js文件时才会引入动画函数 所以要在前面引入 -->
    <script src="./js/animate.js"></script>
    <script src="./js/lb.js"></script>
</head>

<body>
    <div class="w">
        <div class="focus">
            <!-- 左侧按钮 -->
            <a href="javascript:;" class="arrow-l">
                
            </a>
            <!-- 右侧按钮 -->
            <a href="javascript:;" class="arrow-r"></a>
            <!-- 核心的滚动区域 -->
            <ul>
                <li>
                    <a href="#"><img src="upload/focus.jpg" 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>
        </div>
    </div>

</body>

</html>

 

 

ok,轮播图克服掉了。

春意盎然,我的寒假还在继续。。。。。。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章