As animações são o que transforma sites simples em experiências excêntricas e inesquecíveis. Elas dão um pouco de personalidade e unicidade ao seu site e deixam o visitante admirando a estética global.

É claro que os seres humanos amam as coisas bonitas. Todos nós amamos produtos que se encaixam bem nos olhos.

Neste artigo, vamos aprender a criar animações que impressionam usuários com o uso de Framer motion e React-Router-Dom.

Pré-requisitos

Para ser capaz de seguir o que estamos fazendo neste artigo, você deve ter algum conhecimento de React, Framer motion e React-Router-DOM.

Para melhor aprender Framer motion, você pode estudar sua documentação.

Node.js deve também ser instalado no seu sistema, e você deve ter um editor de código funcional. Eu usarei o VS Code.

Como Configurar o Projeto

Para configurar o nosso projeto, vamos usar o Vite para configurar o ambiente de desenvolvimento React.

  1. Abra o terminal no VSCode. Você pode usar Ctrl + backtick(`)

  2. No seu terminal, digite o seguinte comando:

npm create vite@latest
  1. Siga com as instruções para nomear o seu projeto e escolher o framework desejado. No nosso caso, estamos usando React. Este será um projeto de JavaScript.

  2. Vá para o diretório do seu projeto e use npm i no terminal.

  3. Para iniciar seu projeto, use npm run dev.

  4. Lembre-se de limpar seu projeto removendo o código em App.js e seus arquivos CSS na pasta src.

Como Iniciar Framer Motion e React-Router-Dom

  1. Para instalar Framer-motion em seu projeto, abra o terminal e digite:
npm i framer-motion
  1. Para instalar React-Router-DOM em seu projeto, abra o terminal e digite:
npm i react-router-dom

Como Configurar Componentes e Rotação Básica com React-Router-Dom

Vamos configurar os nossos componentes e as páginas a que estaremos roteando para este projeto.

  1. Na pasta src, crie uma nova pasta chamada components.

  2. Adicionaremos quatro arquivos nesta pasta com os nomes Home.jsx, About.jsx, Projects.jsx e Navbar.jsx.

  3. Dentro dos três primeiros, vamos criar um componente funcional do React. Alterar o conteúdo da tag h1 em cada componente:

const Home = () => {
 return (
    <div>
     <h1>Home</h1>
    </div>
 )
 }

 export default Home
  1. No Navbar, precisamos importar Link do React-Router-DOM para criar elementos de ancora. Depois, precisamos criar um container que abrigue nosso logotipo e links de navegação. O logotipo vai linkar os pontos para nossa página inicial.
import {Link} from "react-router-dom"

const Navbar () => {
 return (
     <div className="nav">
      <div className="logo">
         <Link className="nav-link" to="/">Lennythedev</Link>
     </div>
     <div>
        <div className="nav-links">
           <div className="nav-item">
            <Link className="nav-link" to="/">Home</Link>
           </div>
           <div className="nav-item">
            <Link className="nav-link" to="/">About</Link>
           </div>
           <div className="nav-item">
            <Link className="nav-link" to="/">Projects</Link>
           </div>
     </div>
     </div>
     </div>
  )
 }
  1. Agora vamos para o nosso arquivo index.js ou main.js. O objetivo é envolver toda nossa aplicação com BrowserRouter o qual vai habilitar a navegação dentro de nossa aplicação.
import React from "react"
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import './index.css'
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <Router>
      <Routes>
        <Route path='/*' element={<App />} />
      </Routes>
    </Router>
  </React.StrictMode>,
)
  1. Agora em App.js, vamos concluir o passo final de nossa configuração. Vamos importar nossos componentes e algumas funcionalidades de React-Router-DOM e renderizá-los. Usando a funcionalidade useLocation do React-Router-DOM, podemos definir a localização atual das rotas definindo a chave para a rota atual.
import './App.css'
import { Routes, Route, useLocation } from 'react-router-dom'
import NavBar from './components/NavBar';
import Home from './components/Home';
import Projects from './components/Projects';
import About from './components/About';

function App() {
  const location = useLocation();
  return (
    <>
       <NavBar />
       <AnimatePresence mode='wait'>
       <Routes location={location} key={location.pathname}>
        <Route index element={<Home />} />
        <Route path='/projects' element={<Projects />}/>
        <Route path='/about' element={<About />}/>
       </Routes>
       </AnimatePresence>
    </>
  )
}

export default App
  1. Agora podemos adicionar nossos estilos em App.css:
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  color: white;
  font-family: "Fira Sans Condensed", sans-serif;
}

html,
body {
  font-family: "Fira Sans Condensed", sans-serif;
  background: rgb(0, 162, 255);
}

.nav {
  position: fixed;
  width: 100%;
  display: flex;
  justify-content: space-between;
}

.nav-links {
  display: flex;
  cursor: pointer;
}

.logo, .nav-item {
  margin: 2em;
  font-weight: 400;
  font-size: 1.5vw;
}

h1{
  width: 80%;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
  font-weight: 500;
  font-size: 10vw;
  line-height: 1;
  text-transform: uppercase;
}

a {
  text-decoration: none;
  font-weight: 500;
}
  1. Após seguir todos os passos, sua aplicação deveria parecer assim:

página estilizada sem animação

Como Criar Transições Usando Framer Motion

Finalmente, vamos criar nossa animação para as transições entre páginas.

  1. Crie um arquivo em componentes chamado Box.jsx e import motion from framer-motion.

  2. Então, podemos retornar duas divs, com classNames de slide-in e slide-out, uma para entrar e outra para sair.

  3. Inserimos nossa animação nestas divs com a ajuda de framer-motion:

import { motion } from "framer-motion"

export default function Box() {
  return(
    <div>
     <motion.div
        className="slide-in"
        initial={{ scaleY: 0 }}
        animate={{ scaleY: 0 }}
        exit={{ scaleY: 1 }}
        transition={{ duration: 1, ease: [0.22, 1, 0.36, 1] }}
     />
     <motion.div
     className="slide-out"
        initial={{ scaleY: 1 }}
        animate={{ scaleY: 0 }}
        exit={{ scaleY: 0 }}
        transition={{ duration: 1, ease: [0.22, 1, 0.36, 1] }}
     />
    </div>
  )
}
  1. Agora, adicionamos nosso estilo em nosso arquivo CSS para slide-in e slide-out em nosso App.css
.slide-in {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  background: #0f0f0f;
  transform-origin: bottom;
}

.slide-out {
  position: fixed;
  top: 0;
  left: 0;
  height: 100vh;
  background: #0f0f0f;
  transform-origin: top;
}
  1. Finalmente, a última etapa é usar AnimatePresence de framer-motion em nosso arquivo App.js e envolver toda a App em AnimatePresence e definir o modo como wait. Se você quiser aprender mais sobre AnimatePresence, visite as docs do framer-motion.
import './App.css'
import { Routes, Route, useLocation } from 'react-router-dom'
import NavBar from './components/NavBar';
import Home from './components/Home';
import Projects from './components/Projects';
import About from './components/About';
import { AnimatePresence } from 'framer-motion';

function App() {
  const location = useLocation();
  return (
    <>
       <NavBar />
       <AnimatePresence mode='wait'>
       <Routes location={location} key={location.pathname}>
        <Route index element={<Home />} />
        <Route path='/projects' element={<Projects />}/>
        <Route path='/about' element={<About />}/>
       </Routes>
       </AnimatePresence>
    </>
  )
}

export default App
  1. Finalmente, o nosso trabalho deve se parecer com o vídeo abaixo:

Conclusão

Criar animações de páginas múltiplas com Framer Motion e React-Router-Dom melhora a experiência do usuário fornecendo transições suaves.

Esta integração aproveita as capacidades de animação do Framer Motion com as funcionalidades de roteamento do React-Router-Dom, resultando em aplicações web dinâmicas e interativas.