setInterval() 方法创建奇怪的重叠

setInterval() Method creating strange overlap

当我尝试构建一个简单的文本轮播时,我遇到了一个我很难理解的问题。

布局简单。我有一个包装器和我希望轮播循环显示的文本。

但是,据我所知,我遇到的问题似乎来自 setInterval 方法。在动画循环遍历所有文本和 returns 到开头后,显示的第一个和第二个文本之间出现奇怪的重叠。第一个文本会显示动画,但随后 return 会暂时替换第二个文本。

如能帮助理解导致此错误以这种方式呈现的原因,我们将不胜感激。

let animateSlide = setInterval(moveSlide, 1200);

function moveSlide() {
  let carousel = document.getElementById("wordCarousel");
  let firstSlide = carousel.children[0];
  let createID = document.createAttribute("id");

  createID.value = "active";

  firstSlide.setAttributeNode(createID);

  carousel.appendChild(carousel.firstChild);

  carousel.children[carousel.children.length - 1].removeAttribute("id");
}
/* Carousel Styles */

#wordCarousel {
  height: 36px;
  overflow: hidden;
}

  .carouselSlide {
    color: #555;
    font-size: 36px;
  }

#active {
  margin-top: 0px;
  animation-name: example;
  animation-duration: 1.2s;
  animation-timing-function: ease;
}

@keyframes example {
  from {
    margin-top: 0px;
  }
  to {
    margin-top: -40px;
  }
}
<div id="wordCarousel">
  <div class="carouselSlide">
    Item 1
  </div>
  <div class="carouselSlide">
    Item 2
  </div>
  <div class="carouselSlide">
    Item 3
  </div>
  <div class="carouselSlide">
    Item 4
  </div>

</div>

处理 CSS 动画时不要依赖 setInterval。你永远不会有完美的同步。最好考虑像 animationiteration/animationend/animationstart

这样的事件

这是一个更好的主意,代码更少,更容易处理。

let carousel = document.querySelector('#wordCarousel div');

carousel.addEventListener('animationiteration', () => {
  carousel.appendChild(carousel.children[0]);
});
#wordCarousel {
  height: 36px;
  overflow: hidden;
}

.carouselSlide {
  color: #555;
  font-size: 36px;
  line-height:100%; /* line-height will make sure the height is equal to 36px, font-size alone isn't enough  */
}

#wordCarousel > div {
  height:100%;
  animation: example 1s infinite;
}

@keyframes example {
  to {
    transform: translateY(-100%);
  }
}
<div id="wordCarousel">
  <div>
    <div class="carouselSlide">
      Item 1
    </div>
    <div class="carouselSlide">
      Item 2
    </div>
    <div class="carouselSlide">
      Item 3
    </div>
    <div class="carouselSlide">
      Item 4
    </div>
  </div>
</div>