-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Jan Fischer
committed
Apr 6, 2021
1 parent
8a9b8c0
commit b2d2666
Showing
8 changed files
with
279 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
--- | ||
name: ScrollTrigger | ||
menu: Components | ||
--- | ||
|
||
import { Fragment } from 'react'; | ||
import { Playground, Props } from 'docz' | ||
import { Controls, PlayState, ScrollTrigger } from './../../../react-gsap/src/' | ||
import { Tween } from './Tween' | ||
import { Timeline, TargetWithNames } from './Timeline' | ||
|
||
# ScrollTrigger | ||
|
||
The ScrollTrigger component is a small helper for the ScrollTrigger plugin. | ||
|
||
Read the official documentation: https://greensock.com/docs/v3/Plugins/ScrollTrigger | ||
|
||
It's available since version 3.2.0. | ||
Before you also could use the ScrollTrigger plugin by importing/registering and using it in a Tween or Timeline by yourself: | ||
|
||
import { Tween } from 'react-gsap'; | ||
|
||
import { ScrollTrigger } from 'gsap/dist/ScrollTrigger'; | ||
gsap.registerPlugin(ScrollTrigger); | ||
|
||
<Tween | ||
to={{ | ||
x: '300px', | ||
scrollTrigger: { | ||
trigger: '.square', | ||
start: '-200px center', | ||
end: '200px center', | ||
scrub: 0.5, | ||
markers: true, | ||
}, | ||
}} | ||
> | ||
<div className="square" style={{ width: '100px', height: '100px', background: '#ccc' }} /> | ||
</Tween> | ||
|
||
## Basic usage | ||
|
||
With the ScrollTrigger component, it looks like the following. If you don't add a trigger prop, it will use the ref from the Tween target. | ||
|
||
<Playground> | ||
<ScrollTrigger | ||
start="-200px center" | ||
end="200px center" | ||
scrub={0.5} | ||
markers | ||
> | ||
<Tween | ||
to={{ | ||
x: '300px', | ||
}} | ||
> | ||
<div style={{ width: '100px', height: '100px', background: '#ccc' }} /> | ||
</Tween> | ||
<Tween | ||
to={{ | ||
x: '300px', | ||
}} | ||
> | ||
<div style={{ width: '100px', height: '100px', background: '#999' }} /> | ||
</Tween> | ||
</ScrollTrigger> | ||
</Playground> | ||
|
||
## Use "trigger" prop | ||
|
||
Currently it's not possible to change the props on the fly. **So this will not work for the `trigger` prop**: | ||
|
||
const triggerRef = useRef(null); | ||
const [trigger, setTrigger] = useState(triggerRef.current); | ||
|
||
useEffect(() => { | ||
setTrigger(triggerRef.current); | ||
}, []); | ||
|
||
return ( | ||
<> | ||
<ScrollTrigger trigger={trigger}> | ||
<Tween | ||
to={{ | ||
x: '500px', | ||
}} | ||
> | ||
<div>This element gets not tweened by ref</div> | ||
</Tween> | ||
</ScrollTrigger> | ||
|
||
<Square ref={triggerRef}> | ||
This element is the trigger | ||
</Square> | ||
</> | ||
); | ||
|
||
If you want to target a ref directly instead of using a CSS selector you can use a Timeline with a forwardRef target: | ||
|
||
// This is the target component which "exports" 4 refs | ||
const TargetWithNames = forwardRef((props, ref: any) => { | ||
const div1 = useRef(null); | ||
const div2 = useRef<MutableRefObject<any>[]>([]); | ||
const div3 = useRef(null); | ||
const trigger = useRef(null); | ||
|
||
useImperativeHandle(ref, () => ({ | ||
div1, | ||
div2, | ||
div3, | ||
trigger, | ||
})); | ||
|
||
return ( | ||
<div ref={trigger} style={{ textAlign: 'center' }}> | ||
<h3 ref={div1}>THIS</h3> | ||
<SplitChars | ||
ref={(charRef: MutableRefObject<any>) => div2.current.push(charRef)} | ||
wrapper={<h3 style={{ display: 'inline-block' }} />} | ||
> | ||
TEST | ||
</SplitChars> | ||
<h3 ref={div3}>IS A</h3> | ||
</div> | ||
); | ||
}); | ||
|
||
You can then use the key of the exported refs in the `trigger` or `target` props. | ||
If it doesn't find a ref with this key it will use the `trigger` string as CSS selector. | ||
|
||
<Playground> | ||
<ScrollTrigger | ||
trigger="trigger" | ||
start="top center" | ||
end="400px center" | ||
scrub={0.5} | ||
markers={true} | ||
pin={true} | ||
> | ||
<Timeline target={<TargetWithNames />}> | ||
<Tween | ||
from={{ | ||
x: '-100vw', | ||
}} | ||
target="div1" | ||
/> | ||
<Tween | ||
from={{ | ||
x: '-100vw', | ||
}} | ||
target="div3" | ||
/> | ||
<Tween | ||
from={{ | ||
x: '-100vw', | ||
}} | ||
stagger={0.5} | ||
target="div2" | ||
/> | ||
</Timeline> | ||
</ScrollTrigger> | ||
</Playground> | ||
|
||
## Standalone | ||
|
||
If you don't pass children to the component a GSAP ScrollTrigger instance will be created and can be used standalone. | ||
|
||
You can get the instance by calling `getGSAP()` on the ref. | ||
|
||
<Playground> | ||
{() => { | ||
const scrollTrigger = React.useRef(null); | ||
return ( | ||
<Fragment> | ||
<div id="id" style={{width: '100px', height: '100px', background: '#ccc'}}/> | ||
<div id="otherID" style={{width: '100px', height: '100px', background: '#999'}}/> | ||
<ScrollTrigger | ||
ref={scrollTrigger} | ||
trigger="#id" | ||
start="top top" | ||
endTrigger="#otherID" | ||
end="bottom 50%+=100px" | ||
markers | ||
onToggle={self => console.log("toggled, isActive:", self.isActive)} | ||
onUpdate={self => { | ||
console.log("progress:", self.progress.toFixed(3), "direction:", self.direction, "velocity", self.getVelocity()); | ||
}} | ||
/> | ||
<button onClick={() => scrollTrigger.current.getGSAP().disable()}>Disable ScrollTrigger</button> | ||
</Fragment> | ||
) | ||
}} | ||
</Playground> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
--- | ||
name: Use "playState" prop | ||
menu: Instructions | ||
--- | ||
|
||
import { Fragment } from 'react'; | ||
import { Playground } from 'docz' | ||
import { PlayState, Tween } from './../../../react-gsap/src/' | ||
|
||
# Use playState and totalProgress props | ||
|
||
With the playState and progress/totalProgress props you can control a Tween or a Timeline. | ||
So you don't need low-level access to play/reverse/pause/stop or seek to a position. | ||
|
||
From version 3.2.0 on the `playState` prop also works for the initial state and the following states were added: | ||
`restartReverse`, `stopEnd`, `resume`. | ||
|
||
The following gsap functions are called internally, if the `playState` prop change: | ||
|
||
if (playState === PlayState.play) { | ||
gsap.play(); | ||
} else if (playState === PlayState.restart) { | ||
gsap.restart(true); | ||
} else if (playState === PlayState.reverse) { | ||
gsap.reverse(); | ||
} else if (playState === PlayState.restartReverse) { | ||
gsap.reverse(0); | ||
} else if (playState === PlayState.stop) { | ||
gsap.pause(0); | ||
} else if (playState === PlayState.stopEnd) { | ||
gsap.reverse(0); | ||
gsap.pause(); | ||
} else if (playState === PlayState.pause) { | ||
gsap.pause(); | ||
} else if (playState === PlayState.resume) { | ||
gsap.resume(); | ||
} | ||
|
||
<Playground> | ||
{() => { | ||
const [playState, setPlayState] = React.useState(PlayState.pause); | ||
const [totalProgress, setTotalProgress] = React.useState(0) | ||
return ( | ||
<Fragment> | ||
<Tween to={{ x: '300px' }} duration={2} playState={playState} totalProgress={totalProgress}> | ||
<div style={{ width: '100px', height: '100px', background: '#ccc' }} /> | ||
</Tween> | ||
<button onClick={() => setPlayState(PlayState.play)}>play</button> | ||
<button onClick={() => setPlayState(PlayState.restart)}>restart</button> | ||
<button onClick={() => setPlayState(PlayState.reverse)}>reverse</button> | ||
<button onClick={() => setPlayState(PlayState.restartReverse)}>restartReverse</button> | ||
<button onClick={() => setPlayState(PlayState.stop)}>stop</button> | ||
<button onClick={() => setPlayState(PlayState.stopEnd)}>stopEnd</button> | ||
<button onClick={() => setPlayState(PlayState.pause)}>pause</button> | ||
<button onClick={() => setPlayState(PlayState.resume)}>resume</button> | ||
<div> | ||
<input type="range" max="1" step="0.001" value={totalProgress} onChange={(event) => setTotalProgress(event.target.value)} /> | ||
</div> | ||
</Fragment> | ||
) | ||
}} | ||
</Playground> | ||
|