在 vanilla/pure JS 中无限滚动而不产生间隙

make infinite scroll in vanilla/pure JS without creating gap

当一个循环完成后,你就可以看到差距了。我想摆脱它。 它会一个接一个地循环而不会产生间隙。

谁能给我一些时间来解决这个问题..

const scrollAnimation = (function() {
  let element = null;
  // let obejct = {};
  let scroller = true;
  let scrollSpeed = 0;
  let parentElement = null;
  let childElement = null;
  let viewHeight = 0;

  const toggleScrollEvent = function(e) {
    scroller = (e.type == 'mouseenter') ? false : true;
  }


  const setProperty = function(element, obejct) {

    viewHeight = document.querySelector(element).clientHeight

    scrollSpeed = obejct.scrollSpeed;

    // create child element 
    childElement = document.createElement('div');
    childElement.id = 'childElement';

    // append scroll content to  child element 
    let items = document.querySelectorAll(element + ' .item');
    items.forEach(function(item) {
      childElement.appendChild(item)
    });

    // append child element to parent element
    element = document.querySelector(element);
    parentElement = element.appendChild(childElement)

    // set child element top property value manually 200px
    // let hg = childElement.getBoundingClientRect();
    childElement.style.top = viewHeight + 'px';



    parentElement.addEventListener('mouseenter', toggleScrollEvent);
    parentElement.addEventListener('mouseleave', toggleScrollEvent);

  }

  const scrollEelement = function() {
    let posY = parseInt(childElement.style.top);
    if (scroller) {
      if (posY + childElement.clientHeight > 0) {
        childElement.style.top = posY - scrollSpeed + 'px'
      } else {
        childElement.style.top = viewHeight + 'px';
      }
    }
  }

  setInterval(scrollEelement, 50)



  return {
    init: function(element, obejct) {
      setProperty(element, obejct)
    }
  }

})([]);

window.addEventListener("DOMContentLoaded", function() {
  scrollAnimation.init('#parentElement', {
    scrollSpeed: 5,
  });
})
*,
*::after,
*::before {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body,
html {
  margin: 0;
  padding: 0;
}

#parentElement {
  position: relative;
  width: 400px;
  background: #eeeeee;
  height: 200px;
  overflow: hidden;
  border: 2px solid royalblue;
}

#parentElement #childElement {
  padding: 10px;
  position: absolute;
  width: 100%;
  top: 0;
  left: 0;
}
<div id="parentElement">
  <h1 class="item">Start</h1>
  <h1 class="item">Mid</h1>
  <h1 class="item">Mid</h1>
  <h1 class="item">Mid</h1>
  <h1 class="item">Mid</h1>
  <h1 class="item">Mid</h1>
  <h1 class="item">Mid</h1>
  <h1 class="item" style="background: orangered;">End</h1>
</div>

在你的 scrollEelement 函数中,你检查是否需要重新开始滚动,你可以检查当前顶部位置是否小于“.item”之一的高度负值 divs。如果是,请从 div 中删除第一项并在末尾再次附加它。由于这些 div 的高度为 45px,一旦子元素 div 的顶部小于 -45,顶部的“.item”div 就不再可见,可以在 div 的末尾被删除和替换 - 并调整子元素的顶部以添加回 45px 以用于删除的项目。所以:

const scrollAnimation  = (function(){
      let element = null;
      // let obejct = {};
      let scroller = true;
      let scrollSpeed = 0;
      let  parentElement= null;
      let childElement = null;
      let viewHeight = 0;

      const toggleScrollEvent = function (e){
            scroller = (e.type == 'mouseenter') ? false : true;
        }
     

     const  setProperty =  function(element,obejct){

          viewHeight  = document.querySelector(element).clientHeight
       
            scrollSpeed = obejct.scrollSpeed;

            // create child element 
            childElement =  document.createElement('div');
            childElement.id = 'childElement';

           // append scroll content to  child element 
            let items = document.querySelectorAll(element+ ' .item');
            items.forEach(function(item){
              childElement.appendChild(item)
            });

            // append child element to parent element
            element = document.querySelector(element);
            parentElement = element.appendChild(childElement)

            // set child element top property value manually 200px
            // let hg = childElement.getBoundingClientRect();
            childElement.style.top = viewHeight+ 'px';


            
            parentElement.addEventListener('mouseenter',toggleScrollEvent);
            parentElement.addEventListener('mouseleave',toggleScrollEvent);

      } 


    const scrollEelement = function(){
      let posY = parseInt(childElement.style.top);
      // Get the first child div
      let firstDiv = childElement.querySelectorAll(".item")[0];
      // Check its height
      let firstDivHeight = firstDiv.clientHeight;
      // If we are scrolling...
      if(scroller){
        // Find out where the scroll would move to
        let tmppos = posY - scrollSpeed;
        // If it is higher than the height of the first div
        if (tmppos < 0 - firstDivHeight) {
          // remove the first div
          childElement.removeChild(firstDiv);
          // .. and append it to the end
          childElement.appendChild(firstDiv);
          // .. and do the scroll
          childElement.style.top = (tmppos + firstDivHeight) + "px";
        } else {
          // otherwise, just do the scroll
          childElement.style.top = tmppos + "px";
        }
      }
    }

   setInterval(scrollEelement,10)

    return {
      init:function(element,obejct){
       setProperty(element,obejct)
      }
    }

  })([]);

  window.addEventListener("DOMContentLoaded",function(){
    scrollAnimation.init('#parentElement',{
      scrollSpeed:1,
    });
  })
 *,*::after,*::before{
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }
      body,html{
        margin: 0;
        padding: 0;
      }
    
      #parentElement{
        position: relative;
        width: 400px;
        background: #eeeeee;
        height: 200px;
        overflow: hidden;
        border: 2px solid royalblue;
      }
        #parentElement #childElement{
            padding: 10px;
            position: absolute;
            width: 100%;
            top: 0;
            left: 0;
      }
      
<div id="parentElement">
      <h1 class="item">Start</h1>
      <h1 class="item">Mid................<br>..............on two lines</h1>
      <h1 class="item">Mid</h1>
      <h1 class="item">Mid</h1>
      <h1 class="item">Mid</h1>
      <h1 class="item">Mid</h1>
      <h1 class="item">Mid</h1>
      <h1 class="item" style="background: orangered;">End</h1>
  </div>

这是一个主要使用 css 动画的解决方案。

const containerElem = document.querySelector('.container');
const contentElem = document.querySelector('.content');
const contentCloneElem = contentElem.cloneNode(true);
containerElem.appendChild(contentCloneElem);

const pxPerSec = 100;
const contentHeight = contentElem.clientHeight;
containerElem.style.animationDuration = `${contentHeight / pxPerSec}s`;
.infiniteScroll {
  border: 2px solid blue;
  height: 150px;
  overflow: hidden;
}

.container {
  border: 2px solid red;
}

.content {
  border: 1px solid green;
}

@keyframes changePos {
  from {
    transform: translateY(0px);
  }
  to {
    transform: translateY(-50%);
  }
}

.container {
  animation-duration: 5s;
  animation-timing-function: linear;
  animation-name: changePos;
  animation-iteration-count: infinite;
  animation-direction: normal;
}

.container:hover {
  animation-play-state: paused;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Infinite Scroll</title>
</head>
<body>
  <div class="infiniteScroll">
    <div class="container">
      <div class="content">
        <h1 class="item">Start</h1>
        <h1 class="item">Mid</h1>
        <h1 class="item">Mid</h1>
        <h1 class="item">Mid</h1>
        <h1 class="item">Mid</h1>
        <h1 class="item">Mid</h1>
        <h1 class="item">Mid</h1>
        <h1 class="item" style="background: orangered;">End</h1>
      </div>
    </div>
  </div>
</body>
</html>