原生javascript 无缝轮播图

结构:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <title>轮播图</title>
<!--    引入样式文件-->
    <link rel="stylesheet" href="css/index.css">
<!--    引入动画函数-->
    <script src="js/animate.js"></script>
<!--    引入轮播js文件-->
    <script src="js/index.js"></script>
</head>
<body>
<!--轮播窗口-->
<div class="container">
<!--    图片盒子-->
    <div class="img_box">
        <img src="images/p1.gif" alt="">
        <img src="images/p2.gif" alt="">
        <img src="images/p3.gif" alt="">
        <img src="images/p4.gif" alt="">
    </div>
<!--    左右箭头-->
    <a href="javascript:" class="left"> < </a>
    <a href="javascript:" class="right"> > </a>
<!--    小圆点盒子-->
    <div class="dot_box"></div>
</div>
</body>
</html>

样式

.container {
    position: relative;
    width: 500px;
    height: 300px;
    margin: 100px auto;
    overflow: hidden;
}

.img_box {
    position: absolute;
    overflow: hidden;
    width: 2500px;
}

.container img {
    float: left;
    width: 500px;
    height: 300px;
}

a {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    display: none;
    width: 24px;
    height: 40px;
    text-align: center;
    text-decoration: none;
    color: white;
    font-size: 20px;
    line-height: 40px;
}

.container a:hover {
    background-color: rgba(0, 0, 0, .5);
}

.container:hover a {
    display: block;
}

.left {
    left: 0;
}

.right {
    right: 0;
}

.dot_box {
    position: absolute;
    bottom: 10px;
    left: 50%;
    transform: translateX(-50%);
    width: 104px;
    height: 20px;
}

.dot_box span {
    display: inline-block;
    float: left;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    margin: 0 3px;
    text-align: center;
    line-height: 20px;
    color: deepskyblue;
    cursor: pointer;
    background-color: rgba(0, 0, 0, .5);
}

.dot_box .on {
    color: white;
    background-color: #ee3333 !important;
}

动画函数

// 动画原理
// 传入要运动的对象obj  和 运动的距离 target
function animate(obj, target, callback) {  // callback 为回调函数 比如说 运动完成后要对运动对象进行样式改变
    clearInterval(obj.timer);  // 优化
    //var timer = setInterval(function () {
    // 这里用var 声明变量 当每次调用时就会声明一个timer 同时也会占用大量内存
    // 多个对象同时使用时 可能会产生歧义
    obj.timer = setInterval(function () {   // 优化
        var step = (target - obj.offsetLeft) / 10;  // 速度控制
        step = step > 0 ? Math.ceil(step) : Math.floor(step); // 取整 防止BUG
        if (obj.offsetLeft == target) {
            // clearInterval(timer);
            clearInterval(obj.timer);     // 优化
            // if (callback) {    // 如果有回调函数
            //     callback();    // 就进行调用
            // }
            callback && callback();  // 优化
        }
        obj.style.left = obj.offsetLeft + step + 'px';
    }, 15)
}

// 未优化前 多次点击会加速移动 因为调用一次开启一个定时器 多次调用开启了多个定时器
// 解决方法  在运动函数内部 前面添加清除定时器 代码

轮播js

// 加载完成后执行
window.addEventListener('load',function () {
    // 获取元素
    var container = document.querySelector('.container');
    var imgBox = document.querySelector('.img_box');
    var left = document.querySelector('.left');
    var right = document.querySelector('.right');
    var dotBox = document.querySelector('.dot_box');
    // flag 用于节流阀 防止不断点击左右箭头 使轮播加速
    var flag = true;
    // 控制左右箭头点击时移动距离的变量
    var sum = 0;
    // 控制左右箭头点击时小圆点的样式变化的变量
    var sum1 = 0;
    // 根据图片的张数 动态生成 小圆点
    for (var i = 0; i < imgBox.children.length; i++) {
        // 创建span元素
        var span = document.createElement('span');
        // 给span添加数字内容  1 2 3 4
        span.innerHTML = i + 1;
        // 设置自定义属性 作为后面的索引 index = i
        span.setAttribute('index', i);
        // 将span 元素添加到 小圆点盒子里
        dotBox.appendChild(span);
    }

    // 获取所有的小圆点
    var dots = dotBox.querySelectorAll('span');
    // 遍历小圆点 注册点击事件 以及样式
    for (var i = 0; i < dots.length; i++) {
        // 给第一个小圆点添加样式 (默认样式)
        dots[0].className = 'on';
        // 给小圆点注册点击事件
        dots[i].addEventListener('click', function () {
            // 排他思想 先干掉所有小圆点的样式
            for (var j = 0; j < dots.length; j++) {
                dots[j].className = "";
            }
            // 给自己添加样式
            this.className = 'on';
            // 获得当前小圆点的索引值
            var index = this.getAttribute('index');
            // 赋值给左右箭头的变量 实现圆点同步
            sum = index;
            sum1 = index;
            // 设置 flag 为true 防止轮播过程中 突然点小圆点 而flag 还处于 false 的状态 后面轮播不继续
            flag = true;
            // 点击小圆点 时 移动的距离
            animate(imgBox, -index * container.offsetWidth);
        });
    }

    // 克隆第一张图片
    var first = imgBox.children[0].cloneNode(true);
    // 添加到图片盒子
    imgBox.appendChild(first);

    // 右箭头

    right.addEventListener('click', function () {
        // flag 为true 时 执行
        if (flag) {
            // 先将flag 赋值为false 防止不停点击箭头快速轮播
            flag = false;
            // sum 变量控制 轮播循环
            if (sum === dots.length) {
                sum = 0;
                // 瞬间跳到第一张位置 第一张和最后一张 为用一张图片 跳转时肉眼看不出
                imgBox.style.left = '0';
            }
            sum++;
            // 动画移动 继续轮播~ 动画函数里带有回调函数  动画结束 将flag 赋值为true 下一次点击 就可以继续轮播
            animate(imgBox, -sum * container.offsetWidth, function () {
                flag = true;
            });
            // sum1 控制小圆点样式
            sum1++;
            if (sum1 > dots.length - 1) {
                sum1 = 0;
            }
            for (var i = 0; i < dots.length; i++) {
                dots[i].className = '';
            }
            dots[sum1].className = 'on';
        }
    });

    // 左箭头

    left.addEventListener('click', function () {
        if (flag) {
            flag = false;
            if (sum === 0) {
                sum = dots.length;
                imgBox.style.left = '-2000px';
            }
            sum--;
            animate(imgBox, -sum * container.offsetWidth, function () {
                flag = false;
            });
            sum1--;
            if (sum1 < 0) {
                sum1 = dots.length - 1;
            }
            for (var i = 0; i < dots.length; i++) {
                dots[i].className = '';
            }
            dots[sum1].className = 'on';
        }
    });

    // 自动轮播

    var timer = null;
    // 自动轮播函数
    function autoPlay() {
        // 计时器
        timer = setInterval(function () {
            right.click();
        }, 2000)
    }
    // 先调用一次 进入页面时直接轮播
    autoPlay();
    // 鼠标进入 轮播区 清除计时器
    container.addEventListener('mouseenter', function () {
        clearInterval(timer);
    });
    // 鼠标离开 再次调用自动轮播 开启计时器
    container.addEventListener('mouseleave', function () {
        autoPlay();
    })
});

 

posted @ 2019-05-05 21:07  码小龙  阅读(218)  评论(0编辑  收藏  举报