美文网首页基础前端
无缝连续滚动原理的实现

无缝连续滚动原理的实现

作者: CondorHero | 来源:发表于2019-02-07 23:59 被阅读25次
    无缝连续滚动示意图

    原理剖析:
    页面上图片复制一倍在后面,长长的火车在移动:


    滚动图片
    当你赋值的后半段火车的0号头贴到了盒子的左边框的时候,那么就瞬间移动到原点,重新执行动画: 动画原理图
    实现步骤:
    • HTML CSS知识构建静态页面
    • 逻辑实现使用绝对定位
    • JS定时器轮播

    代码的实现

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>无缝连续滚动的实现</title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            .rolling{
                width: 800px;
                height: 130px;
                border: 10px solid #ccc;
                margin: 100px auto;
                position: relative;
                overflow: hidden;
            }
            .rolling .m_unit{
                width: 5000px;  /*这是运动的单位,这个宽度随便取,大一点,最少的大于rolling小于运动盒子的内容*/
                position: absolute;
                top: 0;
                left: 0;
            }
            .rolling ul{
                list-style: none;
            }
            .rolling ul li{
                float: left;
                margin-right: 10px;
            }
        </style>
    </head>
    <body>
        <div class="rolling" id="rolling">
            <div class="m_unit" id="m_unit">
                <ul>
                    <li><a href=""><img src="images/shuzi/0.png" alt="" /></a></li>
                    <li><a href=""><img src="images/shuzi/1.png" alt="" /></a></li>
                    <li><a href=""><img src="images/shuzi/2.png" alt="" /></a></li>
                    <li><a href=""><img src="images/shuzi/3.png" alt="" /></a></li>
                    <li><a href=""><img src="images/shuzi/4.png" alt="" /></a></li>
                    <li><a href=""><img src="images/shuzi/5.png" alt="" /></a></li>
                    <li><a href=""><img src="images/shuzi/6.png" alt="" /></a></li>
                    <li><a href=""><img src="images/shuzi/7.png" alt="" /></a></li>
                </ul>
            </div>
        </div>
    
        <script>
            //得到元素
            var rolling = document.getElementById("rolling");
            var m_unit = document.getElementById("m_unit");
            var listul = m_unit.getElementsByTagName("ul")[0];
            //得到图片的数量,计算折返点用的,折返点就是210 * 图片数量
            var lislength = listul.getElementsByTagName("li").length;
    
            //复制一倍的li  最笨的办法直接把 li 在写一遍
            listul.innerHTML += listul.innerHTML;
    
            //信号量
            var nowleft = 0;
            var timer;
            
            //默认调用move
            move();
            
            //鼠标进入
            rolling.onmouseover = function(){
                clearInterval(timer);
            }
    
            //鼠标离开
            rolling.onmouseout = function(){
                move();
            }
    
            function move(){
                //运动
                timer = setInterval(function(){
                    nowleft -= 3;
                    if(nowleft < -210 * lislength){
                        nowleft = 0;
                    }
                    m_unit.style.left = nowleft + "px";
                },10);
            }
        </script>
    </body>
    </html>
    

    滚动的回拉位置的设置方式:

    • 直接计算写常量,太死板。
    • 等宽,计算个数。可适应 图片个数不同。案例即是这种。
      思考:

    如果图片不等宽,长短不一怎么办?

    解决方法有两个:
    方法1:遍历前半部分(复制一倍之前)所有的li,把所有的li的宽度累加,累加之后就是折返点。offsetWidth,这个东西不带margin。所以累加的时候,有需要得到计算后的margin十分麻烦。所以我们不考虑方法1。
    方法2:我们发现,折返点就是复制的假火车第1张图的offsetLeft值。所以,如果原来的li的个数是lilength,那么假火车的第1张图就是lis[length]。

    先讲教训:
    但是写完发现效果不对,未能达到如期预料。原因 Google 浏览器会把图片延迟加载,以达到最快网络体验。解决办法:

    • 添加 window,onload()设置页面加载完,再加载 js 效果。
    • 添加 img.onload() 事件。

    考虑到页面只有一个 onload,这里选择第二个办法。
    主要程序修改如下:

    for(var i = 0 , count = 0 ; i < imgs.length ; i++){
                imgs[i].onload = function(){
                    count++;
                    if(count == imgs.length){
                        //所有图片加载完毕了,就有折返点了:
                        zhefandian = lis[lislength / 2].offsetLeft;
                        //所有图片加载完毕了,再开始运动
                        move();
                    }
                }
            }
    
            //得到元素
            var rolling = document.getElementById("rolling");   //大盒子
            var m_unit = document.getElementById("m_unit");     //运动单位
            var listul = m_unit.getElementsByTagName("ul")[0];  //ul
            var imgs = listul.getElementsByTagName("img");      //img
    
            //图片的原来数量
            var zhefandian; //折返点
    
            //复制一倍的li
            listul.innerHTML += listul.innerHTML;
            //得到所有li,包括新li
            var lis = listul.getElementsByTagName("li");    
            //所有li的个数,包括新li 
            var lislength = lis.length;     
    
            //现在我们要计算折返点,但是每个li的宽度都不一样,所以现在假火车的开头元素的offsetLeft就是折返点。这个元素是lis[lislength / 2];比较麻烦的是,由于Chrome的机理,如果要读取offsetLeft值必须保证所有图片加载完毕。
            for(var i = 0 , count = 0 ; i < imgs.length ; i++){
                imgs[i].onload = function(){
                    count++;
                    if(count == imgs.length){
                        //所有图片加载完毕了,就有折返点了:
                        zhefandian = lis[lislength / 2].offsetLeft;
                        //所有图片加载完毕了,再开始运动
                        move();
                    }
                }
            }
    
            //信号量
            var nowleft = 0;
            var timer;
    
            //鼠标进入
            rolling.onmouseover = function(){
                clearInterval(timer);
            }
    
            //鼠标离开
            rolling.onmouseout = function(){
                move();
            }
    
            function move(){
                clearInterval(timer);
                //运动
                timer = setInterval(function(){
                    nowleft -= 5;
                    if(nowleft < -zhefandian){
                        nowleft = 0;
                    }
                    m_unit.style.left = nowleft + "px";
                },20);
            }
        </script>
    

    小tip:因页面加载图片有延迟,可以给页面添加一个加载背景,一个 GIF 图片的背景。

    相关文章

      网友评论

        本文标题:无缝连续滚动原理的实现

        本文链接:https://www.haomeiwen.com/subject/xgagsqtx.html