当另一个元素的高度发生变化时,GSAP Scrolltrigger 动画开始/结束位置不会更新
我有两个区域,当页面滚动时,使用 GSAP ScrollTrigger 在 h1
元素上向上滚动 h3
动画。在这两个区域之间有一个元素,即笔中的绿色框,它可以通过单击按钮和 GSAP 动画来更改高度。
问题是,当绿色框高度减小时,第二个标题区域的开始/结束位置不会改变(如页脚区域中页面下方的开始/结束标记所示)。因此,当 h3
元素按预期从底部进入屏幕时,滚动动画不会开始。
我打算尝试使用计时器来观察 window.document.documentElement.scrollHeight 的变化,并以某种方式重置或刷新动画,但这看起来很黑客。我缺少 GSAP 的某种方法来处理这种情况吗?
Codepen,这不是实际用例,但演示了问题。
let { Button, Container } = ReactBootstrap
if (typeof window !== undefined) {
gsap.registerPlugin(ScrollTrigger)
}
const App = () => {
const box = React.useRef(null),
titleContainer = React.useRef(null),
titleScroller1 = React.useRef(null),
titleScroller2 = React.useRef(null),
title = React.useRef(null)
let boxFullSize = true
function resizeBox() {
if (boxFullSize) {
gsap.to(box.current, {
height: "500px"
})
boxFullSize = false
} else {
gsap.to(box.current, {
height: "1000px"
})
boxFullSize = true
}
}
React.useEffect(() => {
[titleScroller1, titleScroller2].forEach( x => {
gsap.to(x.current, {
y: "-100px",
scrollTrigger: {
trigger: x.current,
start: "top bottom",
scrub: true,
markers: true
}
})
})
})
return (
<div className="app">
<Container className="hero" fluid="true">
<h1>Scroll</h1>
</Container>
<Container>
<Button onClick={resizeBox}>Resize Box</Button>
<div className="titleContainer" ref={titleContainer}>
<h1 className="lgHeading">Big Heading 1</h1>
<div ref={titleScroller1} className="titleScroller">
<h3 className="title" ref={title}>Small Heading 1</h3>
<div className="lineAfter"></div>
</div>
</div>
<div className="box" ref={box}>
Box
</div>
</Container>
<Container>
<div className="titleContainer" ref={titleContainer}>
<h1 className="lgHeading">Big Heading 2</h1>
<div ref={titleScroller2} className="titleScroller">
<h3 className="title" ref={title}>Small Heading 2</h3>
<div className="lineAfter"></div>
</div>
</div>
</Container>
<footer>
<p>Footer</p>
</footer>
</div>
)
}
ReactDOM.render(<App />, document.getElementById("app"))
I have two areas where as the page is scrolled a h3
animates, using GSAP ScrollTrigger, up over an h1
element. Between these two areas is an element, the green box in the pen, that changes height with a button click and GSAP animation.
The problem is that when the green box height is reduced, the start/end positions for the second heading area do not change (as indicated by the start/end markers being further down the page in the footer area). So the scroll animation does not start when the h3
element enters the screen from the bottom as expected.
I was going to try with a timer to watch for a change in window.document.documentElement.scrollHeight
and reset or refresh the animation somehow but that seems very hackish. There must be a way with GSAP I am missing to handle this situation?
Codepen, it's not the actual use case but demonstrates the issue.
let { Button, Container } = ReactBootstrap
if (typeof window !== undefined) {
gsap.registerPlugin(ScrollTrigger)
}
const App = () => {
const box = React.useRef(null),
titleContainer = React.useRef(null),
titleScroller1 = React.useRef(null),
titleScroller2 = React.useRef(null),
title = React.useRef(null)
let boxFullSize = true
function resizeBox() {
if (boxFullSize) {
gsap.to(box.current, {
height: "500px"
})
boxFullSize = false
} else {
gsap.to(box.current, {
height: "1000px"
})
boxFullSize = true
}
}
React.useEffect(() => {
[titleScroller1, titleScroller2].forEach( x => {
gsap.to(x.current, {
y: "-100px",
scrollTrigger: {
trigger: x.current,
start: "top bottom",
scrub: true,
markers: true
}
})
})
})
return (
<div className="app">
<Container className="hero" fluid="true">
<h1>Scroll</h1>
</Container>
<Container>
<Button onClick={resizeBox}>Resize Box</Button>
<div className="titleContainer" ref={titleContainer}>
<h1 className="lgHeading">Big Heading 1</h1>
<div ref={titleScroller1} className="titleScroller">
<h3 className="title" ref={title}>Small Heading 1</h3>
<div className="lineAfter"></div>
</div>
</div>
<div className="box" ref={box}>
Box
</div>
</Container>
<Container>
<div className="titleContainer" ref={titleContainer}>
<h1 className="lgHeading">Big Heading 2</h1>
<div ref={titleScroller2} className="titleScroller">
<h3 className="title" ref={title}>Small Heading 2</h3>
<div className="lineAfter"></div>
</div>
</div>
</Container>
<footer>
<p>Footer</p>
</footer>
</div>
)
}
ReactDOM.render(<App />, document.getElementById("app"))
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不是最好的......但有效......
Not best.... But works...
使用refresh()函数刷新所有滚动触发器。 这里是文档。
这是一个示例:
例如,如果单击按钮时元素展开,导致高度发生变化,则您需要做的是在发生这种情况时刷新滚动触发位置。
例如,对于多个扩展元素
这仅在高度变化是即时的情况下才有效,如果您有过渡,请参见下文。
如果改变高度的元素有一个过渡
在这种情况下,元素改变高度并有一个过渡属性,页面的高度不会立即改变,因此滚动触发器将计算错误。
如果是这样,请为
transitionend
使用事件侦听器,如下所示(此示例是如果您有多个可能更改高度的元素,例如手风琴):现在,每当手风琴完成高度更改时,所有元素都会滚动触发器将刷新。
确保您正在收听的元素是实际正在转换的元素!例如,如果 .accordion__body 正在改变高度,请听它,而不是它的
transitionend
的父级Use the refresh() function to refresh all of your scroll triggers. Here are the docs.
Here's an example:
If, for example, when you click a button an element expands, causing the height to change, what you need to do is refresh the scroll trigger positions when that happens.
E.g. for multiple expanding elements
This only works if the height change is instant, if you have a transition, see below.
If the elements changing height have a transition
In this case where the elements change height and have a transition property, the height of the page doesn't change instantly, so the scroll triggers will calculate incorrectly.
If so, use an event listener for
transitionend
like so (this example is if you have multiple elements which may change height, like an accordion for example):Now everytime an accordion has finished changing height, all scroll triggers will refresh.
Make sure the element you are listening to is the one that is actually transitioning! E.g. if the .accordion__body is what is changing height, listen to that, not it's parent for the
transitionend