DEV Community

Cover image for Create animations like PowerPoint slides in React with framer-motion and react-intersection-observe
FargusMD
FargusMD

Posted on

Create animations like PowerPoint slides in React with framer-motion and react-intersection-observe

Well, I’m a little bit far from use of animation libraries and kind of, but at my last project we had such a request:

  1. Clients want a webpage that will have similar effects as a presentation in PowerPoint. On mousewheel we change our slides (previous and next)
  2. 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.
  3. 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***

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

Quick review on this libs:

  1. Framer-Motion — actually the package that helps us to animate our react components. API here: https://www.framer.com/api/motion/
  2. *react-intersection-observer *— react implementation of the Intersection Observer API to tell you *when an element enters or leaves the viewport *(from official description). Docs here: https://github.com/thebuilder/react-intersection-observer#readme
  3. famous lodash **— well, we need only **debounce function . Debounce description from official docs : Creates a debounced function that delays invoking func until after wait milliseconds have elapsed since the last time the debounced function was invoked.

Now, we start to count steps:

  1. Create Sections — Slides. Giving them a width and height of 100%, also setting them id. id must be different for all sections. our App.js look like:
    styles.css looks like that:
    • 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).
  • we create we flex center text and add some font size to text .
  • some color to each section individually
    Each section looks like that :
  • nothing special, just a section tag with an ID (later we will add actions using this id! so important to each section to add a different id. ./sections/Section1.jsx (all sections contains same code)
    Now, we have sections, we have our packages setted up, let’s do some coding!

Every page has 4 effects:

  1. Animation that is played when section is on viewport( visible )

  2. Animation that is played when user is leaving outport(hidden)

  3. If user goes next section, we play exit animation for next section (next)

  4. 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


*./useObserverHook.jsx
*So, what we did there:
  • 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)
Enter fullscreen mode Exit fullscreen mode



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
, and for section — 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
component (navigation — on scroll we switch out the slide and leave 0.4s to play animations for sections):


And some small updates on sections, and we get this effects :
a) for drawer — previous and next
b) for content — hidden and visible

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

Top comments (0)