使用Intersection Observer API延迟加载元素

4
我正在使用Intersection Observer API来在用户滚动到内容时显示元素。它工作正常,但我想延迟
的显示时间
,如果有4个
,我希望第一个
出现后0.5秒再出现下一个...不要同时出现。在这个示例中,效果只适用于第一个class,如果有多个class(就像这里有的那样),它将不会应用于下一个img classes,只适用于第一个。你可以在这个页面底部看到这个示例。
<section id="staff" style="padding-top: 100px;">
  <div class="col-lg-12 mx-auto mb-5">
    <div class="container">
      <div class="row icons-info">
        <div class="col-xs-12 col-sm-6 col-md-6 col-lg-3">
          <img class="floating show-bottom" src="img/Muñeco 1-08.png">
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras nibh justo, tincidunt sed felis vitae, egestas scelerisque eros. </p>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-6 col-lg-3 ">
          <img class="floating" src="img/Muñeco 2-08.png">
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras nibh justo, tincidunt sed felis vitae, egestas scelerisque eros.</p>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-6 col-lg-3 ">
          <img class="floating" src="img/Muñeco 3-08.png">
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras nibh justo, tincidunt sed felis vitae, egestas scelerisque eros.</p>
        </div>
        <div class="col-xs-12 col-sm-6 col-md-6 col-lg-3">
          <img class="floating" src="img/Muñeco 1-08.png">
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras nibh justo, tincidunt sed felis vitae, egestas scelerisque eros. </p>
        </div>
      </div>
    </div>
  </div>     
</section>

JS

// Instantiate a new Intersection Observer
let observer7 = new IntersectionObserver(onEntry7);
let staff = document.querySelector('.floating');

let element7 = document.querySelector("#staff p");
observer7.observe(element7);

function onEntry7(entry7) {
  if (entry7[0].isIntersecting) {
    staff.classList.add("show-bottom");
  }
}

CSS

.floating {opacity: 0; transition: 1s opacity;}
.floating.show-bottom {opacity: 1;  
  animation: movefromtop 1s alternate infinite;
  animation-iteration-count: 1;
  animation-fill-mode:  forwards;}
@keyframes movefromtop {
  from {
    transform: translateY(-5em);
  }
  to {
    transform: translateY(0em);
  }
}
1个回答

4
使用 querySelectorAll() 获取所有内部div元素,然后使用 forEach 为所有元素调用您的 observer.observe() 方法。在观察器中,使用 target 属性查询内部图像并向其添加 show-bottom 类。
要在每个动画之间添加延迟,您需要通过返回一个Promise 并使用 setTimeout() 创建动画链。同时确保不会在多次交叉触发同一元素时对同一元素进行多次链接。为此,请使用数组animatedElements 跟踪正在进行动画处理的元素。
如果只想在开始交叉后对元素执行一次动画,则可以在观察器上调用 unobserve 来注销进一步的交叉事件。
注意:我编辑了您的HTML / CSS以使网格在片段中工作,以演示当多个元素位于同一行时的顺序动画效果。 我还在内部div中添加了一个 with-img 类,以便我们可以查询它们并将它们传递给观察方法。

const onEntry7 = animateSequence('.floating', 'show-bottom');
const observer7 = new IntersectionObserver(onEntry7);
const allElements7 = document.querySelectorAll('#staff div.with-img');
allElements7.forEach(e => observer7.observe(e));

function animateSequence(targetSelector, classToAdd, delay = 500) {
  const animatedElements = [];
  let chain = Promise.resolve();

  function show(e) {
    return new Promise((res, rej) => {
      setTimeout(() => {
        e.classList.add(classToAdd);
        res();
      }, delay);
    });
  }
  return function(entries) {
    entries.forEach(entry => {
      if (entry.intersectionRatio > 0) {
        const elem = entry.target.querySelector(targetSelector);
        if (!animatedElements.includes(elem)) {
          animatedElements.push(elem);
          console.clear();
          console.log('chaining', ...animatedElements.map(e => e.getAttribute('data--name')));
          chain = chain.then(() => show(elem));
          observer7.unobserve(entry.target);
        }
      }
    })
  }
}
.floating {
  opacity: 0;
  transition: 1s opacity;
  width: 157px;
  height: 220px;
}
.floating.show-bottom {
  opacity: 1;  
  animation: movefromtop 1s alternate infinite;
  animation-iteration-count: 1;
  animation-fill-mode:  forwards;
}
@keyframes movefromtop {
  from { transform: translateY(-5em); }
  to { transform: translateY(0em); }
}
section#staff {
  margin-top: 200px;
  margin-bottom: 200px;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
Scroll Down
<section id="staff" style="padding-top: 100px;">
  <div class="col-lg-12 mx-auto mb-5">
    <div class="container">
      <div class="row icons-info">
        <div class="with-img col-xs-12 col-xs-6 col-sm-6 col-md-6 col-lg-3">
          <img class="floating" src="https://lagaleramagazine.es/rucab/img/Muñeco 1-08.png" data--name="1">
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras nibh justo, tincidunt sed felis vitae, egestas scelerisque eros. </p>
        </div>
        <div class="with-img col-xs-12 col-xs-6 col-sm-6 col-md-6 col-lg-3 ">
          <img class="floating" src="https://lagaleramagazine.es/rucab/img/Muñeco 2-08.png" data--name="2">
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras nibh justo, tincidunt sed felis vitae, egestas scelerisque eros.</p>
        </div>
        <div class="with-img col-xs-12 col-xs-6 col-sm-6 col-md-6 col-lg-3 ">
          <img class="floating" src="https://lagaleramagazine.es/rucab/img/Muñeco 3-08.png" data--name="3">
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras nibh justo, tincidunt sed felis vitae, egestas scelerisque eros.</p>
        </div>
        <div class="with-img col-xs-12 col-xs-6 col-sm-6 col-md-6 col-lg-3">
          <img class="floating" src="https://lagaleramagazine.es/rucab/img/Muñeco 1-08.png" data--name="4">
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras nibh justo, tincidunt sed felis vitae, egestas scelerisque eros. </p>
        </div>
      </div>
    </div>
  </div>     
</section>


可以检查一下我的页面吗?https://lagaleramagazine.es/rucab/index.html 我已经应用了,但仍然只显示第一个元素...我不知道我做错了什么。 - Pedro Corchero Murga
@Pedro Corchero Munga,我更新了答案以包括延迟和修复错误,然后我将我的代码插入到您的页面中,现在它可以正常工作了。希望这有所帮助! - jo_va
我刚刚清除了它,谢谢。当图片被插入时,我如何应用悬停样式?谢谢。 - Pedro Corchero Murga
@Pedro Corchero Murga,嗯,好问题,你能否发布一个相关的CSS作为单独的问题?我快速查看了你的代码,我认为这不是一个容易解决的问题,也与这个问题所涉及的延迟问题无关。 - jo_va
谢谢 @jo_va,我会问这个问题。我们开始吧!https://stackoverflow.com/questions/55208057/avoid-intersection-observer-resets-when-mouseout-element - Pedro Corchero Murga
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接