22
Create animations like PowerPoint slides in React with framer-motion and react-intersection-observe
- Clients want a webpage that will have similar effects as a presentation in PowerPoint. On mousewheel we change our slides (previous and next)
- This PowerPoint effects should be available only on a desktop view (viewport 1200px and up). But for 1200px and down we must have a normal scrollable page.
- Time resource — critical low(well as always because need in some days to be in a production)
Do not to waste your time, check out final codesandbox here:
***https://codesandbox.io/s/motion-framer-sample-3-l2y9x?file=/src/App.js:0-1912***
***https://codesandbox.io/s/motion-framer-sample-3-l2y9x?file=/src/App.js:0-1912***
Assuming all these criterias, the only option is to use a library with a good documentation( no need to reinvent the wheel) and a ready CRA init project. After CRA install, we add these libraries:
npm i framer-motion react-intersection-observer lodash
npm i framer-motion react-intersection-observer lodash
Quick review on this libs:
Now, we start to count steps:
- we reset margin and borders for all elements (margin:0; padding:0) and create sections with a width and height of 100% of container(container is 100vh and 100vw from viewport).
Every page has 4 effects:
Animation that is played when section is on viewport( visible )
Animation that is played when user is leaving outport(hidden)
If user goes next section, we play exit animation for next section (next)
If user returns back to previous section, we play different exit animation (previous).
Well, let’s implement a custom hook that does all these. Also a file that constains all our constants ( delay! of course… we need a delay for our debounce function , that will optimize our wheel event listener)
./constants.js
we set by default hidden state of our animation, and if it is on viewport, with help of useInView hook we set state to **visible.
useEffect(() => {
if (inView) {
setVariant("visible");
} else setVariant("hidden");
}, [inView]);
Also we create a debounced function to trigger state change when user scrolls up or down, also we add a flag isFirst and *isLast *(well you dont need to go on previous section if you are on last section and viceversa)
const ***onMouseScroll*** = **debounce**((e) => {
if (e.deltaY > 0 && variant === "**visible**")
setVariant(isLast ? "**visible**" : "**next**")
if (e.deltaY < 0 && variant === "**visible**")
setVariant(isFirst ? "**visible**" : "**previous**")
}, MAIN_DELAY)
A codesandbox with sample files:
Now, let’s implement that hook on Sections1.jsx!
— First, we’re gonna create a *./constants.js *file and export MAIN_DELAY constant we’re we declare it to 600ms (well, this actually is debounce value for our hook — we can infinite scroll, but event will be trigerred after last “wheel” effect )
— Let’s console.log our sandbox, to be sure that we going on the right way:

— Now we have variants for triggering animation on mouse wheel , so next step we will do that. To do that we need to import motion from motion-framer and wrap our sections with motion. *Well, we got something like that:
To create these PowerPoint*ish slide effects, we need to create a separate div that will be positionated absolute on top of a section, and with different variants of animations, so we update our *./styles.css *with this block of code:
So, when user use wheel down event, we play for drawer — *drawerVar
sectionVar. *Code sandbox here:
And last small step, is just to switch our pages/slides on same mouse wheel event.
To do that we need to update our *App.jsx
And last small step, is just to switch our pages/slides on same mouse wheel event.
To do that we need to update our *App.jsx

Final results on codesandbox here:
***https://codesandbox.io/s/motion-framer-sample-3-l2y9x?file=/src/App.js:0-1912***
> Happy Coding!
***https://codesandbox.io/s/motion-framer-sample-3-l2y9x?file=/src/App.js:0-1912***
> Happy Coding!