JavaScript实现无缝轮播(全注释并附带点击切换效果)

拥有以下效果

  1. 无缝切换
  2. 缓冲效果 (带有缓冲框架 在末尾)
  3. 点击左右切换
  4. 点击小按钮图片切换
  5. 自动播放(移入停止)

原理
先上结构代码再说原理

<body>
<div id="banner">
    <ul class="pic">
        <li><img src="img/maldives_4.jpg" alt="pic1"/></li>
        <li><img src="img/maldives_1.jpg" alt="pic1"/></li>
        <li><img src="img/maldives_2.jpg" alt="pic1"/></li>
        <li><img src="img/maldives_3.jpg" alt="pic1"/></li>
        <li><img src="img/maldives_4.jpg" alt="pic1"/></li>
        <li><img src="img/maldives_1.jpg" alt="pic1"/></li>
    </ul>
    <ul class="btn">	//点击切换按钮(可在JS中改为移入)
        <li class="active"></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
    <div class="LRbtn">	//左右切换按钮
        <span>&lt;</span>
        <span class="right">&gt;</span>
    </div>
</div>
</body>

可以看到 结构搭建里一共使用了6张图 而看到的效果却只使用了4

首先来说 :

如果不使用伪首页图片会出现什么状态?
你会发现当图片走到最后一张图过后 会反弹 回到第一张,这样的效果根本不符合所谓的无缝轮播,反弹出现的效果也不美观。

解决办法:
我们利用伪首页伪末尾图 也就是 在第一张的图片前放最后一张图 末尾放第一张,图片依然正常滚动 当图片走到 伪首页图时(从右往左走) 我们使他的父级数值调转到真正的的第一张图的位置, 所以当图片继续运动时,就会从第二张继续运动, 利用视觉差来巧妙的达到了 无缝轮播(无限轮播)

在这里插入图片描述
CSS样式

<style>
        * {
            margin: 0;
            padding: 0;
        }
        li {
            list-style: none;
        }

        img {
            display: block;
        }

        #banner {
            width: 800px;
            height: 533px;
            margin: 0 auto;
            position: relative;
            overflow: hidden;
        }

        #banner .pic {
            position: absolute;
            left: -800px;   // 让图片呈现为真正的第一张
            top: 0;
            width: 4800px;
        }

        #banner .pic li {
            float: left;
        }

        #banner .btn {
            position: absolute;
            left: 50%;
            bottom: 50px;
            transform: translateX(-50%);
        }

        #banner .btn li {
            float: left;
            width: 20px;
            height: 20px;
            background-color: #ccc;
            margin: 0 5px;
            border-radius: 50%;
            font-size: 0;
        }

        #banner .btn .active {
            background-color: #ff0;
        }

        #banner .LRbtn {
            position: absolute;
            left: 0;
            top: 50%;
            transform: translateY(-50%);
            width: 100%;
        }

        .LRbtn span {
            float: left;
            width: 30px;
            height: 30px;
            background-color: rgba(255, 255, 0, 0.5);
            font-size: 20px;
            line-height: 30px;
            text-align: center;
            color: #000;
            cursor: pointer;
        }
        #banner .LRbtn .right {
            float: right;
        }
    </style>

JS代码呈现:

 <script>
        window.onload = function () {

            var obanner = document.getElementById('banner');    //获取最外层父级盒子
            var opic = document.getElementsByClassName('pic')[0];   //获取ul
            var opicli = opic.getElementsByTagName('li');            // 获取每一个li
            var obtn = document.getElementsByClassName('LRbtn')[0];          //  左右两个切换按钮父级
            var obtnclivc = obtn.getElementsByTagName('span');          //  左右连个切换按钮
            var osbtn = document.getElementsByClassName('btn')[0];    //  获取小按钮的父级
            var osbtnli = osbtn.getElementsByTagName('li');        //获取小按钮
            var index = 1;              //声明一个状态值
            var timer = '';             //声明一个时间容器

           timer = setInterval(move, 2000);    //定时器开启

            obanner.onmouseenter = function () {
                clearInterval(timer);           //移入最外层父级盒子 清除定时器
            };
            obanner.onmouseleave = function () {
                timer = setInterval(move, 1000);    //移除外层父级盒子 打开定时器
            };


            obtnclivc[0].onclick = function () {    // 左点击切换
                index -= 2;
                // index-=2理由:封装的函数中已存在index++,如果继续使用index--就不起作用了 故此index-=2
                move();     // 调用运动函数
                console.log(index);
            };

            obtnclivc[1].onclick = function () {    // 右点击切换
                move(); // 调用运动函数
                console.log(index);
            };


            for (i = 0; i < osbtnli.length; i++) {
                osbtnli[i].index = i;

                // 循环遍历所有的小按钮 同时保存当前按钮的下标值
                osbtnli[i].onclick = function () {
                    for (var j = 0; j < osbtnli.length; j++) {
                        osbtnli[j].className = "";
                        //清除所有小按钮的类名
                    }
                   index = this.index+1;
              //  统一index 值 并且使当前index值加1
                    this.className = 'active';
                    //给当前小按钮添加类名
                    bufmove(opic, {'left': -(index) * 800});
                    //JS封装好了的运动框架 后面会发 让ul的left值随 index值的变换而变换 800是一张图片的宽度
                }

            }


            function move() {   //运动函数
                index++;
                if (index < 0) {
                    opic.style.left = -3200 + 'px';
                 // opic的宽度跳到本体的最后张图;(利用视觉差)
                    index = 3;
                 //让index为3 做到伪无限图的效果
                }
                if (index > 5) {
                    opic.style.left = -800 + 'px';
                    // opic的宽度跳到本体的第一张图;
                    index = 2;
                //让index为2 做到伪无限图的效果
                }
                for (i = 0; i < osbtnli.length; i++) {
                    osbtnli[i].className = '';
                    //清除所有小按钮的类名
                }
                if (index == 5) {
                    osbtnli[0].className = 'active';
                    //当index值为5时 也就是走到了 附第一张时
                    // 小按钮的类名又回到第一个也就是按钮下标为0的时候
                } else if (index == 0) {
                    osbtnli[3].className = 'active';
                    //当index值为0时 也就是走到了 附最后一张时
                    // 小按钮的类名跳到最后一个就是按钮下标为3的时候
                } else {
                    osbtnli[index - 1].className = 'active';
                    //index-1是因为初始状态值为0 我们要让小按钮的小标从0开始
                }
                bufmove(opic, {'left': -index * 800});
                //JS封装好了的运动框架 让ul的left值随 index值的变换而变换 800是一张图片的宽度
            }
        }
    </script>

缓冲框架

//用法bufmove(obox,{opacity:0.2,left:500});
//     bufmove(obox2,{opacity:0.2,left:500,width:500},function(){
//    bufmove(obox2,{opacity:1,left:1000});
//      } );
function  bufmove(obj,jsn,endFn){    
// obj 对象     jsn  (target 终止值jsn[attr] attr属性选择) endFn回调函数
    clearInterval(  obj.timer);
    for(var attr in jsn){
        if(attr== 'opacity'){
            jsn[attr] *= 100;
        }
    }

    obj.timer = setInterval(function(){
        tag =  true;                    // 假设全部到达终点
        for(var attr in jsn){
            if(attr =='opacity'){
                var cur = parseFloat(getstyle(obj,attr)*100);
            }else{
                var cur = parseInt(getstyle(obj,attr));  //当前位置
            }
            var speed =  (   jsn[attr] - cur)/10;                               
            //速度:(目标值- 当前值)/缩放系数          (500 -  0 )/10 = 50
            speed =  speed>0 ? Math.ceil(speed): Math.floor(speed);   
       // 根据速度正负值来判断 取整的方向  如果速度大于0时 向右运动 故此 数值向右取整

            if(cur != jsn[attr]){      
            //  当当前 并等于目标时   状态为假  重新执行  当所有值相同时才为真
                tag =false;
            }

            if(attr =='opacity'){
                obj.style[attr] =  (cur+speed)/100;
            }else{
                obj.style[attr] =  cur+speed + 'px';  
                    //  [] 括号里面能承载变量和字符串
            }
        }

        if(tag){                 
          //  状态为真后  关闭定时器
            clearInterval( obj.timer);  
               // 关闭定时器之后 再调用函数
            if(endFn){                //  回调
                endFn();
            }
        }

    },50)
}
发布了8 篇原创文章 · 获赞 4 · 访问量 1782
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 深蓝海洋 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览