zoukankan      html  css  js  c++  java
  • [JavaScript]继续完善无缝轮播

    无缝轮播

    完整代码:GitHub

    效果预览:GitHub

    之前的轮播思路:

    1:图片主要使用flex定位加上transform:translateX(),配合JS代码,完成图片切换。缺点:不能进行无缝轮播,图片进行到最后一张要原路返回切换到第一张。

    开始时

    结束时

    2:图片主要使用position:absolute定位,加上状态机,配合JS代码,完成轮播。缺点:只能无缝轮播,不能点击按钮跳转到某一张图片。

    详情请戳这里

    开始时

    跳转中

    跳转中

    跳转后


    我们能不能既能用按钮控制图片轮播的同时,还可以让他进行无缝自动轮播?

    思路:
    把轮播的第一张图片A1复制到最后一张图片后面,命名为C1,把最后一张图片A(n)复制到第一张图片前面,命名为C2;
    每当点击按钮从第一张图片直接切换到最后一张图片的时候,不是切到A(n),而是切到C2,然后再用JS控制隐藏切换动画,从C2切到A(n);每当点击按钮从最后一张图片切换到第一张图片时,不是切到A1,而是切到C1,然后再用JS控制隐藏切换动画,从C1切到A1;其他图片照常切换。

    真正的轮播过程是这样的:

    当点击按钮想要直接从A1跳转到C1时:
    开始时

    轮播中

    轮播结束

    当点击按钮想要直接从A3跳转到A1时:

    开始时

    轮播时

    轮播结束

    除了第一张图片和最后一张图片,其他图片照常轮播:

    轮播

    轮播

    轮播

    既然了解了这个轮播的思路,开始coding:


    构建HTML

    <div>
        <p>轮播效果图4</p>
        <div class="window4">
            <div class="images4" id="images4">
                <img src="./img/function-01.jpg" alt="" width=960 height=540>
                <img src="./img/git-01.jpg" alt="" width=960 height=540 >
                <img src="./img/JQUERY-01.jpg" alt="" width=960 height=540>
                <img src="./img/内存-01.jpg" alt="" width=960 height=540>
                <img src="./img/数组-01.jpg" alt="" width=960 height=540>
            </div>
        </div>
        <div class="controls" id="controls">
            <button id="prev">上一张</button>
            <button id="next">下一张</button>
        </div>
        <div class="bnCtrl4" id="bnCtrl4">
            <button >第1张</button>
            <button >第2张</button>
            <button >第3张</button>
            <button >第4张</button>
            <button >第5张</button>
        </div>
    </div>
    

    构建CSS

    主要是构建一个轮播框和利用flex进行图片排列。

    .window4 {
         960px;
        border: 1px solid red;
        margin: 30px auto;
        overflow: hidden;
    }
    .images4 {
        display: flex;
        transition: all 1s;
    }
    .images4 img{
         100%;
    }
    .bnCtrl4 {
        text-align: center;
    }
    .controls{
        text-align: center;
    }
    .controls button{
        margin: 5px;
    }
    .bnCtrl4 button{
        margin: 5px;
    }
    

    先实现图片切换功能

    先模拟每一张图片是怎么进行轮播的:

    // jQuery获取图片
    let $images4 = $('#images')
    let $imgs = $images4.children('img')
    
    //获取按钮
    let $button = $('#bnCtrl4 button')
    

    每当点击按钮时,对应的图片进行切换:

    // 切换到下一张图片
    $button4.eq(0).on('click',function(){
        $images4.css({transform:'translateX(-960px)'})
    })
    $button4.eq(1).on('click',function(){
        $images4.css({transform:'translateX(-960px)'})
    })
    $button4.eq(2).on('click',function(){
        $images4.css({transform:'translateX(-960px)'})
    })
    $button4.eq(3).on('click',function(){
        $images4.css({transform:'translateX(-960px)'})
    })
    $button4.eq(4).on('click',function(){
        $images4.css({transform:'translateX(-960px)'})
    })
    

    再实现图片无缝切换

    克隆图片

    克隆第一张图片放在最后一张图片的后面,克隆最后一张图片放在第一张图片的前面:

    $firstCopy = $img.eq(0).clone(true)
    $lastCopy = $img.eq($img.length - 1).clone(true)
    
    $images4.addchild($firstCopy)
    $images4.prepend($lastCopy)
    
    // 封装成函数
    function makeFakeSlides(){
        let $firstCopy = $imgs.eq(0).clone(true)
        let $lastCopy = $imgs.eq($imgs.length-1).clone(true)
        $images4.append($firstCopy)
        $images4.prepend($lastCopy)
    }
    

    区分第一个按钮和最后一个按钮

    首先给每个按钮一个current,以代表当前的位置,相当于设置一个路标。

    //设置初始路标
    let current = 0
    $images4.css({transform:'translateX(-960px)'})
    
    $button4.eq(0).on('click',function(){
        $images4.css({transform:'translateX(-960px)'})
        current = 0
    })
    $button4.eq(1).on('click',function(){
        $images4.css({transform:'translateX(-1920px)'})
        current = 1
    })
    $button4.eq(2).on('click',function(){
        $images4.css({transform:'translateX(-2880px)'})
        current = 2
    })
    $button4.eq(3).on('click',function(){
        $images4.css({transform:'translateX(-3840px)'})
        current = 3
    })
    $button4.eq(4).on('click',function(){
        $images4.css({transform:'translateX(-4800px)'})
        current = 4
    })
    

    在正常情况下,如从1-2-3-4,按钮2按下时会接收按钮1传递的current=0,然后把current改为1;按钮3按下时,会接收按钮2传递的current=1,然后把current改为2;...以此类推;

    特殊情况是,从按钮5按到按钮1;或者是从按钮1直接按到按钮5,这其中的转变过程我们要用JS来加以判断:

    //设置初始路标
    let current = 0
    $images4.css({transform:'translateX(-960px)'})
    
    $button4.eq(0).on('click',function(){
        if(current == 4){
            //直接切换到第一张图片(即我们复制的C2)
            $images4.css({transform:'translateX(0px)'})
        }else{
            $images4.css({transform:'translateX(-960px)'})
            current = 0
        }
    })
    $button4.eq(1).on('click',function(){
        $images4.css({transform:'translateX(-1920px)'})
        current = 1
    })
    $button4.eq(2).on('click',function(){
        $images4.css({transform:'translateX(-2880px)'})
        current = 2
    })
    $button4.eq(3).on('click',function(){
        $images4.css({transform:'translateX(-3840px)'})
        current = 3
    })
    $button4.eq(4).on('click',function(){
        if(current == 0){
            //直接切换到最后一张图片(即我们复制的C1)
            $images4.css({transform:'translateX(-5760px)'})
        }else{
            $images4.css({transform:'translateX(-4800px)'})
            current = 4
        }
    })
    

    接下来切换图片,从克隆的图片上悄悄地快速地转到真正的图片上:

    利用小技巧 offset(),隐藏切换动画。

    //设置初始路标
    let current = 0
    
    $button4.eq(0).on('click',function(){
        if(current == 4){
            //直接切换到第一张图片(即我们复制的C2)
            $images4.css({transform:'translateX(0px)'})
                .one('transitionend',function(){
                     $images4.hide()
                        .offset()
                        $images4.css({transform:'translateX(-960px)'})
                        .show()
                    })
                })
        }else{
            $images4.css({transform:'translateX(-960px)'})
            current = 0
        }
    })
    $button4.eq(1).on('click',function(){
        $images4.css({transform:'translateX(-1920px)'})
        current = 1
    })
    $button4.eq(2).on('click',function(){
        $images4.css({transform:'translateX(-2880px)'})
        current = 2
    })
    $button4.eq(3).on('click',function(){
        $images4.css({transform:'translateX(-3840px)'})
        current = 3
    })
    $button4.eq(4).on('click',function(){
        if(current == 0){
            //直接切换到最后一张图片(即我们复制的C1)
            $images4.css({transform:'translateX(-5760px)'})
             .one('transitionend',function(){
                    $images4.hide()
                    .offset()
                    $images4.css({transform:'translateX(-4800px)'})
                    .show()
                })
        }else{
            $images4.css({transform:'translateX(-4800px)'})
            current = 4
        }
    })
    

    这么简陋重复的代码,就完成了无缝轮播的功能了!

    优化代码

    给按钮添加事件代理,把代码进一步抽象出来:

    function bindEvents(){
        $('#bnCtrl4').on('click','button',function(e){
    
            //获取当前点击按钮
            let $buttons = $(e.currentTarget)
    
            //获取按钮的位置下标
            let index = $buttons.index()
    
            if(current === $button4.length-1 && index === 0){
            $images4.css({transform:`translateX(${-($button4.length+1) * 960}px)`})
            .one('transitionend',function(){
                $images4.hide()
                    .offset()
                    $images4.css({transform:`translateX(${-(index+1)*960}px)`})
                    .show()
                    })
            }else if(current === 0 && index === $button4.length-1){
                $images4.css({transform:`translateX(0px)`})
                .one('transitionend',function(){
                    $images4.hide()
                        .offset()
                        $images4.css({transform:`translateX(${-(index+1) * 960}px)`})
                        .show()
                    })
            }else{
                $images4.css({transform:`translateX(${-(index+1) * 960}px)`})
            }
        current = index
        })
    }
    

    进一步抽象

    把轮播功能提取出来,可以提供接口,添加更多的功能:

    function bindEvents(){
        $('#bnCtrl4').on('click','button',function(e){
            let $buttons = $(e.currentTarget)
            let index = $buttons.index() 
            goToSlides(index)
        })
    }
    
    function goToSlides(index){
        if(index > $button4.length - 1){
            index = 0
        }else if(index < 0 ){
            index = $button4.length -1
        }
        if(current === $button4.length-1 && index === 0){
            $images4.css({transform:`translateX(${-($button4.length+1) * 960}px)`})
            
            // 当动画结束时添加一个时间,执行函数,让他快速转回第一张图片
            .one('transitionend',function(){
                
                //小技巧,先hide()再show(),中断动画
                $images4.hide()
                        .offset()
                        $images4.css({transform:`translateX(${-(index+1)*960}px)`})
                        .show()
                    })
        }else if(current === 0 && index === $button4.length-1){
            $images4.css({transform:`translateX(0px)`})
            
            // 当动画结束时添加一个时间,执行函数,让他快速转回第一张图片
            .one('transitionend',function(){
                
                //小技巧,先hide()再show(),中断动画
                $images4.hide()
                        .offset()
                        $images4.css({transform:`translateX(${-(index+1) * 960}px)`})
                        .show()
                    })
        }else{
            $images4.css({transform:`translateX(${-(index+1) * 960}px)`})
        }
        current = index
    }
    

    添加自动轮播

    这就是为什么要提取出goToSlides()的原因:

    setInterval(function(){
        goToSlides(current + 1)
    },2000)
    

    添加其他功能

    //上下页功能
    $(next).on('click',function(){
        goToSlides(current + 1)
    })
    
    $(prev).on('click',function(){
        goToSlides(current - 1)
    })
    
    //鼠标移入,轮播暂停;鼠标移出,轮播继续
    let thisTimer = setInterval(function(){
        goToSlides(current + 1)
    },2000)
    
    $('.window4').on('mouseenter',function(){
        window.clearInterval(thisTimer)
    }).on('mouseleave',function(){
        thisTimer = setInterval(function(){
            goToSlides(current + 1)
        },2000)
    })
    
    

    总结

    总的来说,自己创建一个轮播的过程是十分鬼畜的!要考虑很多东西,即使是听老师讲一遍,自己再做出来,对于现在的我也有难度。
    这里更多的是直接给出结果,而没有更多地给出思考的过程,这是一种失误,也是我一直想要避免、一直在更正的东西。
    只能多看看人家的博文,多学习了。

  • 相关阅读:
    WPF画辐射图
    WPF 获取表格里面的内容
    C# 动态生成Html地图文件
    C#如何关闭指定进程
    oracle EM 打不开 503 |OracleDBConsoleorcl 启动不了
    oracle windows 下修复无监听错误-12541/12514
    Oracle 命令汇总
    oracle 函数 bitand 与 decode
    一.Git 初步扫盲
    修改字段类型
  • 原文地址:https://www.cnblogs.com/No-harm/p/9601547.html
Copyright © 2011-2022 走看看