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:
  • Framer-Motion — actually the package that helps us to animate our react components. API here: https://www.framer.com/api/motion/
  • *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
  • 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:
  • 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:
  • 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
    Final results on codesandbox here:
    ***https://codesandbox.io/s/motion-framer-sample-3-l2y9x?file=/src/App.js:0-1912***
    > Happy Coding!

    22

    This website collects cookies to deliver better user experience

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