How to create a zoom transition animation effect using React & Framer Motion?

Interruption in the user’s experience while navigating between pages can often lead to them going off the website. We could improve on that by adding page transitions in our web application which could lead to an uninterrupted experience for the user.


This content originally appeared on DEV Community and was authored by Parmeet Singh Asija

Interruption in the user's experience while navigating between pages can often lead to them going off the website. We could improve on that by adding page transitions in our web application which could lead to an uninterrupted experience for the user.

This article aims to explain, how we could create one such page transition animation for a gallery web app using React & Framer Motion. So let's get started with it then! 😉

Project Initialisation

npx create-react-app gallery

Install Dependencies

yarn add framer-motion styled-components polished react-use

Images Data Structure

All the images are stored in an array of the following data structure:

{
   "name": string,
   "location": string,
   "variant": string,
   "creator": {
     "name": string,
     "avatar": url_string
   }
}

App Component

ImageGrid component is called inside App component.

// path:src/App.js

import { useState } from "react";

// External
import styled from "styled-components";
import { motion } from "framer-motion";

// Components
import ImageGrid from "./components/image-grid";

// Styles
import { Container, Heading } from "./styles/globalStyles";

const AppStyles = styled(motion.div)`
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #f8ebe2;
`;

const App = () => {
  // index of the image being shown
  const [selectedImage, setSelectedImage] = useState(-1);

  return (
    <AppStyles>
      <Container>
        <Heading>Explore 🇮🇳</Heading>
        <ImageGrid
          selectedImage={selectedImage}
          setSelectedImage={setSelectedImage}
        />
      </Container>
    </AppStyles>
  );
};

export default App;

Image Grid Component

This page shows all the images in a masonry grid layout.

// path:src/components/image-grid/index.js

import { useState, useEffect } from "react";

// External
import { AnimateSharedLayout } from "framer-motion";
import { useLockBodyScroll } from "react-use";

// Components
import SinglePicture from "./single-picture";

// Styles
import { Grid } from "./styles";

// Data
import data from "../../data.json";

const ImageGrid = ({ selectedImage, setSelectedImage }) => {
  // helps in preventing body from scrolling when an image page is being shown
  const [isScrollLocked, setScrollLocked] = useState(false);

  useLockBodyScroll(isScrollLocked);

  useEffect(() => {
    if (selectedImage !== -1) {
      setScrollLocked(true);
    } else {
      setScrollLocked(false);
    }
  }, [selectedImage]);

  return (
    <AnimateSharedLayout>
      <Grid>
        {data.images.map((data, index) => (
          <SinglePicture
            key={`${data.name}-${index}`}
            isSelected={selectedImage === index}
            index={index}
            setSelectedImage={setSelectedImage}
            data={data}
          />
        ))}
      </Grid>
    </AnimateSharedLayout>
  );
};

export default ImageGrid;

Single Picture

This page shows a single image with some image metadata.

// path: src/components/image-grid/single-picture.jsx

// Styles
import { Flex } from "../../styles/globalStyles";
import {
  Image,
  SinglePictureContainer,
  Back,
  InfoCard,
  Name,
  PhotographerName,
  Avatar,
  Location,
} from "./styles";

// Assets
import images from "../../images";
import { CloseIcon } from "../../images/CustomIcons";

// animation config and variants
const spring = {
  type: "spring",
  stiffness: 500,
  damping: 30,
};

const backVariants = {
  initial: {
    opacity: 0,
    y: -20,
  },
  animate: { opacity: 1, y: 0 },
};

const cardVariants = {
  initial: {
    opacity: 0,
    y: 100,
    x: "-50%",
  },
  animate: { opacity: 1, y: 0, x: "-50%" },
};

const SinglePicture = ({
  isSelected,
  setSelectedImage,
  index,
  data: { creator, location, name, variant },
}) => {
  const goBack = () => {
    setSelectedImage(-1);
  };

  return (
    <SinglePictureContainer
      isSelected={isSelected}
      layoutId={`card-container--index-${index}`}
      transition={spring}
      variant={variant}
    >
      {isSelected && (
        <Back
          onClick={goBack}
          initial="initial"
          animate="animate"
          exit="initial"
          transition={{ delay: 0.2, duration: 0.5 }}
          variants={backVariants}
        >
          <CloseIcon />
        </Back>
      )}
      <Image
        src={images[name]}
        alt={name}
        onClick={() => {
          setSelectedImage(index);
        }}
        isExpanded={isSelected}
        layoutId={`card-image--index-${index}`}
      />
      {isSelected && (
        <InfoCard
          initial="initial"
          animate="animate"
          exit="initial"
          transition={{ delay: 0.1, duration: 0.5 }}
          variants={cardVariants}
        >
          <Location>{location}</Location>
          <Name>{name}</Name>
          <Flex>
            <Avatar
              image={
                !!creator.avatar
                  ? `${creator.avatar}?q=10&w=50`
                  : images.avatarFallback
              }
            />
            <PhotographerName>{creator.name}</PhotographerName>
          </Flex>
        </InfoCard>
      )}
    </SinglePictureContainer>
  );
};

export default SinglePicture;

Conclusion

And there we have it, the gallery page transition animation is ready. The Code is available on Github. Would love to hear your valuable feedback in the comments down below.

See you guys 👋🏻  in the next article of this Component series!

Happy coding & Stay safe! ✨

Follow me on Twitter & Instagram for more!

This article can also be read on my website


This content originally appeared on DEV Community and was authored by Parmeet Singh Asija


Print Share Comment Cite Upload Translate Updates
APA

Parmeet Singh Asija | Sciencx (2021-10-01T20:49:47+00:00) How to create a zoom transition animation effect using React & Framer Motion?. Retrieved from https://www.scien.cx/2021/10/01/how-to-create-a-zoom-transition-animation-effect-using-react-framer-motion/

MLA
" » How to create a zoom transition animation effect using React & Framer Motion?." Parmeet Singh Asija | Sciencx - Friday October 1, 2021, https://www.scien.cx/2021/10/01/how-to-create-a-zoom-transition-animation-effect-using-react-framer-motion/
HARVARD
Parmeet Singh Asija | Sciencx Friday October 1, 2021 » How to create a zoom transition animation effect using React & Framer Motion?., viewed ,<https://www.scien.cx/2021/10/01/how-to-create-a-zoom-transition-animation-effect-using-react-framer-motion/>
VANCOUVER
Parmeet Singh Asija | Sciencx - » How to create a zoom transition animation effect using React & Framer Motion?. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/10/01/how-to-create-a-zoom-transition-animation-effect-using-react-framer-motion/
CHICAGO
" » How to create a zoom transition animation effect using React & Framer Motion?." Parmeet Singh Asija | Sciencx - Accessed . https://www.scien.cx/2021/10/01/how-to-create-a-zoom-transition-animation-effect-using-react-framer-motion/
IEEE
" » How to create a zoom transition animation effect using React & Framer Motion?." Parmeet Singh Asija | Sciencx [Online]. Available: https://www.scien.cx/2021/10/01/how-to-create-a-zoom-transition-animation-effect-using-react-framer-motion/. [Accessed: ]
rf:citation
» How to create a zoom transition animation effect using React & Framer Motion? | Parmeet Singh Asija | Sciencx | https://www.scien.cx/2021/10/01/how-to-create-a-zoom-transition-animation-effect-using-react-framer-motion/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.