使用 IntersectionObserver 在视图中触发 gsap 动画
Using IntersectionObserver to trigger gsap animations when in view
https://codepen.io/OscarTBeamish/pen/1130adf7066be1a390a3cb4d9c46f212
我正在使用 class 'animate' 遍历元素,然后为每个元素添加一个时间轴,然后使用 IntersectionObserver 在视图中播放动画。
// Intersection observer stuff
var callback = function (entries, observer) {
entries.forEach(function (entry) {
if (entry.intersectionRatio > 0) {
entry.target.timeline.play();
}
});
};
var observerOptions = {
rootMargin: '100px',
threshold: 1.0
};
var observer = new IntersectionObserver(callback, observerOptions);
// Animation logic
var animations = document.querySelectorAll(".animate");
animations.forEach(function (el, index) {
masterTL = new TimelineLite({
paused: true
});
var tl = new TimelineLite();
if($(el).hasClass('background')) {
tl.to(el, {
ease: 'power2.inOut',
x: 0,
duration: 1
})
// return
masterTL.add(tl);
el.timeline = masterTL;
}
else {
tl.to(el, {
ease: 'power2.inOut',
y: 0,
duration: .6
})
.to(el, {
ease: 'power2.inOut',
opacity: 1,
delay: -.5,
duration: .5,
})
masterTL.add(tl, index * 0.02);
el.timeline = masterTL;
}
// console.log('still goin');
observer.observe(el);
});
我已经成功地在文本上做到了这一点,但我想在元素还具有 class 或 'background' 时触发不同的补间。
有些帮助会很棒这个想法本身一开始可能是错误的。我基本上只是想在视图中触发每个 class 的不同补间。
编辑: 由于发布了这个答案,GreenSock 出来 ScrollTrigger which is more useful than intersection observers. Read the docs 以了解更多信息!
原回答
这里的问题是你的元素永远不会满足交集观察者的阈值,因为你有 transform: translateX(-100%)
,即使滚动到父部分也是如此。
因此,您可能应该
- 使用不同的元素作为在 视图中的那个元素的触发器(我的建议)。
- 将 -100% 更改为 -99% 并将阈值更改为某个值(如 0)以满足要求。
- 使用具有不同参数的第二个相交观察器来仅与有问题的元素相交。
旁注:您应该使用 gsap
而不是 TimelineMax
/TweenMax
东西。这是来自 GSAP 2。有关详细信息,请参阅 the GSAP 3 notes。您的代码稍微清理了一下(没有实施上述任何建议):
// Intersection observer stuff
var callback = function (entries, observer) {
entries.forEach(function (entry) {
if (entry.intersectionRatio > 0) {
entry.target.timeline.play();
}
});
};
var observerOptions = {
rootMargin: '100px',
threshold: 1.0
};
var observer = new IntersectionObserver(callback, observerOptions);
// Animation logic
var animations = document.querySelectorAll(".animate");
animations.forEach(function (el, index) {
el.timeline = gsap.timeline({paused: true});
if(el.classList.contains('background')) {
el.timeline.to(el, {
ease: 'power2.inOut',
x: 0,
duration: 1,
})
}
else {
el.timeline.to(el, {
ease: 'power2.inOut',
y: 0,
duration: .6
})
.to(el, {
ease: 'power2.inOut',
opacity: 1,
delay: -.5,
duration: .5,
})
}
observer.observe(el);
});
https://codepen.io/OscarTBeamish/pen/1130adf7066be1a390a3cb4d9c46f212
我正在使用 class 'animate' 遍历元素,然后为每个元素添加一个时间轴,然后使用 IntersectionObserver 在视图中播放动画。
// Intersection observer stuff
var callback = function (entries, observer) {
entries.forEach(function (entry) {
if (entry.intersectionRatio > 0) {
entry.target.timeline.play();
}
});
};
var observerOptions = {
rootMargin: '100px',
threshold: 1.0
};
var observer = new IntersectionObserver(callback, observerOptions);
// Animation logic
var animations = document.querySelectorAll(".animate");
animations.forEach(function (el, index) {
masterTL = new TimelineLite({
paused: true
});
var tl = new TimelineLite();
if($(el).hasClass('background')) {
tl.to(el, {
ease: 'power2.inOut',
x: 0,
duration: 1
})
// return
masterTL.add(tl);
el.timeline = masterTL;
}
else {
tl.to(el, {
ease: 'power2.inOut',
y: 0,
duration: .6
})
.to(el, {
ease: 'power2.inOut',
opacity: 1,
delay: -.5,
duration: .5,
})
masterTL.add(tl, index * 0.02);
el.timeline = masterTL;
}
// console.log('still goin');
observer.observe(el);
});
我已经成功地在文本上做到了这一点,但我想在元素还具有 class 或 'background' 时触发不同的补间。
有些帮助会很棒这个想法本身一开始可能是错误的。我基本上只是想在视图中触发每个 class 的不同补间。
编辑: 由于发布了这个答案,GreenSock 出来 ScrollTrigger which is more useful than intersection observers. Read the docs 以了解更多信息!
原回答
这里的问题是你的元素永远不会满足交集观察者的阈值,因为你有 transform: translateX(-100%)
,即使滚动到父部分也是如此。
因此,您可能应该
- 使用不同的元素作为在 视图中的那个元素的触发器(我的建议)。
- 将 -100% 更改为 -99% 并将阈值更改为某个值(如 0)以满足要求。
- 使用具有不同参数的第二个相交观察器来仅与有问题的元素相交。
旁注:您应该使用 gsap
而不是 TimelineMax
/TweenMax
东西。这是来自 GSAP 2。有关详细信息,请参阅 the GSAP 3 notes。您的代码稍微清理了一下(没有实施上述任何建议):
// Intersection observer stuff
var callback = function (entries, observer) {
entries.forEach(function (entry) {
if (entry.intersectionRatio > 0) {
entry.target.timeline.play();
}
});
};
var observerOptions = {
rootMargin: '100px',
threshold: 1.0
};
var observer = new IntersectionObserver(callback, observerOptions);
// Animation logic
var animations = document.querySelectorAll(".animate");
animations.forEach(function (el, index) {
el.timeline = gsap.timeline({paused: true});
if(el.classList.contains('background')) {
el.timeline.to(el, {
ease: 'power2.inOut',
x: 0,
duration: 1,
})
}
else {
el.timeline.to(el, {
ease: 'power2.inOut',
y: 0,
duration: .6
})
.to(el, {
ease: 'power2.inOut',
opacity: 1,
delay: -.5,
duration: .5,
})
}
observer.observe(el);
});