代码之家  ›  专栏  ›  技术社区  ›  Rence

无限水平滑块上下有不同的动画

  •  1
  • Rence  · 技术社区  · 8 年前

    我有一个滑块,可以有一个未定义的项目数量,可以滚动通过两个按钮。

    这个prev和next函数都有相同的基本思想,将所需的项放在div的末尾或开头,然后使用margin left设置动画。请看下面的代码。

    问题: 只要慢慢按下按钮,这两个动画都是一样的。 但是,由于某些原因,如果快速按下按钮,这两种功能的动画都不同。

    对于下一个函数,它是一个步进动画。 对于上一个动画,它是一个平滑的动画,但在转换期间它确实与相邻项重叠。

    var slider = document.getElementById('wrapper');
    var currentPosition = 0;
    var elementCount = slider.childElementCount;
    
    (function() {
        let brand = slider.getElementsByClassName('brands-brand')[elementCount - 1];
        slider.insertBefore(brand, slider.firstChild);
        brand.style.marginLeft = '-10%';
    })();
    
    window.myFunctionNext = function() {
        let brand = slider.getElementsByClassName('brands-brand')[0];
        brand.style.marginLeft = '0px';
        slider.appendChild(brand);
        slider.getElementsByClassName('brands-brand')[0].style.marginLeft = '-10%';
        start=false;
    }
    
    window.myFunctionPrev = function() {
        let brand = slider.getElementsByClassName('brands-brand')[elementCount - 1];
        brand.style.marginLeft = '-10%';
        slider.insertBefore(brand, slider.firstChild);
        slider.getElementsByClassName('brands-brand')[1].style.marginLeft = '0%'; 
    }
    .brands-wrapper {
      white-space: nowrap;
      overflow: hidden;
      font-size: 0;
      position: relative;
      width: 1000px;
      border: 1px solid black;
      box-sizing: border-box;
      }
    
    .brands-slide {
      position: relative;
      left: 0;
      top: 0;
      box-sizing: border-box;
    }
    
    .brands-brand {
      transition: all 0.6s ease;
      display: inline-block;
      z-index: 1;
      width: 10%;
      font-size: medium;
      font-size: initial;
      padding-left: 10px;
      padding-right: 10px;
      border: 1px solid red;
      box-sizing: border-box;
      }
      
      img {
        width: 100%;
        height: 150px;
        object-fit: contain;
      }
    <div id="slider" class="brands-wrapper ">
      <div id="wrapper" class="brands-slide animate">
        <div class="brands-brand">
            <img src="http://via.placeholder.com/91x90" alt="brandname" />
        </div>
        <div class="brands-brand">
            <img src="http://via.placeholder.com/91x100" alt="brandname" />
        </div>
        <div class="brands-brand">
            <img src="http://via.placeholder.com/491x200" alt="brandname" />
        </div>
        <div class="brands-brand">
            <img src="http://via.placeholder.com/191x300" alt="brandname" />
        </div>
        <div class="brands-brand">
            <img src="http://via.placeholder.com/150x200" alt="brandname" />
        </div>
        <div class="brands-brand">
            <img src="http://via.placeholder.com/150x100" alt="brandname" />
        </div>
        <div class="brands-brand">
            <img src="http://via.placeholder.com/41x70" alt="brandname" />
        </div>
        <div class="brands-brand">
            <img src="http://via.placeholder.com/91x70" alt="brandname" />
        </div>
        <div class="brands-brand">
            <img src="http://via.placeholder.com/150x150" alt="brandname" />
        </div>
        <div class="brands-brand">
            <img src="http://via.placeholder.com/91x70" alt="brandname" />
        </div>
        <div class="brands-brand">
            <img src="http://via.placeholder.com/77x77" alt="brandname" />
        </div>
        <div class="brands-brand">
            <img src="http://via.placeholder.com/88x88" alt="brandname" />
        </div>
      </div>
    </div>
    
    <button onclick="myFunctionPrev()">
        Prev
    </button>
    <button onclick="myFunctionNext()">
    Next
    </button>

    以下是我尝试过的一些其他方法,但到目前为止都没有奏效: https://jsfiddle.net/Sirence/rbdLgso7/19/

    理想的解决方案是动画和prev一样平滑,但没有重叠。不过,如果两个动画的表现都相同,那就已经很好了。

    1 回复  |  直到 8 年前
        1
  •  1
  •   Ryan Stark    8 年前

    当快速按下next/prev按钮时,javascrpit会在css转换完成之前更改dom。当向右滚动时,这将导致异步转换。向左滚动时,最左边的元素(仍在边距转换过程中)将在转换完成之前从dom中删除,因此新的最左边的元素将捕捉到相应位置。新的最左边元素中没有更改css属性,因此不应用转换。

    您应该能够通过在代码中添加控制机制来实现您的目标,该机制确保在当前转换完成之前不会修改dom。

    下面的javascript如果添加到现有代码中,应该提供一种持续同步滚动的机制,直到达到所需的滚动目标。

    var animation = 0;                              // Which way and how many tiles to rotate
    var animate_active = false;                     // Run status
    
    window.myFunctionStart = function() {
        if ( !animate_active ) {                    // Do not start if already running
            setTimeout(myFunctionAnimate, 1);       // Start callback
            animate_active = true;                  // Sets running flag
        }
    }
    
    window.myFunctionAnimate = function() {
        if ( animation < 0 ) {                      // If direction = Prev
            myFunctionPrev();                       // Execute transition
            animation += 1;                         // Itterate towards 0
            setTimeout(myFunctionAnimate, 600);     // Continue callback at 0.6s intervals ( should match css transition )
        }
        else if ( animation > 0 ) {                 // If direction = Next
            myFunctionNext();                       // Execute transition
            animation -= 1;                         // Itterate towards 0
            setTimeout(myFunctionAnimate, 600);     // Continue callback at 0.6s intervals ( should match css transition )
        }
        else animate_active = false;                // If no more animations required, stop callback
    }
    

    要使用此代码,“下一步”和“上一步”按钮应如下所示。

    <button onclick="animation -= 1; myFunctionStart();">Prev</button>
    <button onclick="animation += 1; myFunctionStart();">Next</button>
    

    您可能还想将css转换从 ease linear ,否则转换看起来将不稳定。