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)
    })
    
    

    总结

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

  • 相关阅读:
    leetcode 190 Reverse Bits
    vs2010 单文档MFC 通过加载位图文件作为客户区背景
    leetcode 198 House Robber
    记忆化搜索(DP+DFS) URAL 1183 Brackets Sequence
    逆序数2 HDOJ 1394 Minimum Inversion Number
    矩阵连乘积 ZOJ 1276 Optimal Array Multiplication Sequence
    递推DP URAL 1586 Threeprime Numbers
    递推DP URAL 1167 Bicolored Horses
    递推DP URAL 1017 Staircases
    01背包 URAL 1073 Square Country
  • 原文地址:https://www.cnblogs.com/No-harm/p/9601547.html
Copyright © 2011-2022 走看看