Menu fechado

Crie Transições de Página Asíncronas em JavaScript Puro

Transições de Página

Introdução às Transições de Página

As transições de página são fundamentais para uma experiência de usuário agradável, pois podem aprimorar a usabilidade e a aparência do aplicativo. Uma boa transição de página cria uma sensação de continuidade e fluidez, tornando a navegação mais agradável. Neste artigo, exploraremos como criar um sistema de transição de página leve e assíncrono utilizando JavaScript vanilla, GSAP e Vite.

Importância das Transições de Página

Transições de página são essenciais para uma experiência de usuário agradável, permitindo que os usuários naveguem entre diferentes páginas do aplicativo sem interrupções. Além disso, elas podem criar uma sensação de profundidade e dimensão, tornando o aplicativo mais interessante e atraente.

Desafios de Implementar Transições de Página

Implementar transições de página pode ser um desafio, pois requer habilidades técnicas e criativas. É necessário considerar fatores como a velocidade da transição, a aparência e a compatibilidade com dispositivos e navegadores. Além disso, a transição deve ser leve e assíncrona para evitar atrasos e melhorar a experiência do usuário.

Arquitetura do Sistema de Transição de Página

O sistema de transição de página que criaremos utilizará a seguinte arquitetura:

* JavaScript vanilla para a lógica de negócios
* GSAP para as animações e transições
* Vite para a configuração e gerenciamento do projeto

Essa arquitetura permitirá que criemos um sistema de transição de página leve e assíncrono, fácil de configurar e gerenciar.

Implementação do Sistema de Transição de Página

A implementação do sistema de transição de página será feita em várias etapas:

1. Criação da estrutura básica do sistema
2. Implementação das animações e transições com GSAP
3. Configuração da lógica de negócios com JavaScript vanilla
4. Testes e depuração do sistema

Essas etapas permitirão que criemos um sistema de transição de página robusto e eficaz, atendendo às necessidades dos usuários e desenvolvedores.

Conclusão

As transições de página são fundamentais para a experiência do usuário e criar um sistema de transição de página leve e assíncrono pode melhorar a usabilidade e aparência do aplicativo. Neste artigo, exploramos como criar um sistema de transição de página utilizando JavaScript vanilla, GSAP e Vite, e implementar as animações e transições com GSAP.

Configuração do Projeto

Criação do Projeto com Vite

npm create vite@latest

Estrutura de Pastas


projeto/
├── node_modules/
├── public/
├── src/
│   ├── main.js
│   └── style.css
├── .gitignore
├── index.html
├── package-lock.json
└── package.json

Configuração Básica do HTML e CSS





  
  
  Transições de Página com JavaScript Vanilla
  


  

Implementação do Roteador

Definição de Rotas


const rotas = {
  "/": {
    namespace: "home",
    carregador: () => import("./pages/home/home.js"),
  },
  "/pagina-alternativa": {
    namespace: "pagina-alternativa",
    carregador: () => import("./pages/pagina-alternativa/pagina-alternativa.js"),
  },
};

Classe Roteador


class Roteador {
  constructor() {
    this.namespaceAtual = null;
    this.estaTransicionando = false;
  }

  async carregarPaginaInicial() {
    const caminho = window.location.pathname;
    const rota = rotas[caminho];
    if (!rota) return;
    const moduloPagina = await rota.carregador();
    const conteudo = document.getElementById("page_content");
    if (!conteudo) return;
    conteudo.innerHTML = moduloPagina.default();
    const container = document.querySelector('[data-transition="container"]');
    if (container) {
      container.setAttribute("data-namespace", rota.namespace);
    }
    this.namespaceAtual = rota.namespace;
  }

  async navegar(caminho) {
    if (this.estaTransicionando || window.location.pathname === caminho) return;
    window.history.pushState({}, "", caminho);
    await this.executarTransicao(caminho);
  }

  async executarTransicao(caminho) {
    if (this.estaTransicionando) return;
    this.estaTransicionando = true;
    try {
      const rota = rotas[caminho];
      if (!rota || this.namespaceAtual === rota.namespace) return;
      const moduloPagina = await rota.carregador();
      const proximoHTML = moduloPagina.default();
      const conteudo = document.getElementById("page_content");
      if (conteudo) {
        conteudo.innerHTML = proximoHTML;
      }
      const container = document.querySelector('[data-transition="container"]');
      if (container) {
        container.setAttribute("data-namespace", rota.namespace);
      }
      this.namespaceAtual = rota.namespace;
    } finally {
      this.estaTransicionando = false;
    }
  }
}

Instância do Roteador


export const roteador = new Roteador();

Motor de Transição

Para criar o motor de transição, precisamos implementar a lógica de transição assíncrona, criando um segundo container, injetando o conteúdo do próximo página nele, executando a animação entre os dois containers e, finalmente, limpando o ambiente.

Criando o Motor de Transição


import { gsap } from "../lib/index.js";
import { transicaoPadrao } from "./animacoes/transicaoPadrao.js";

export async function executarTransicao({ proximoHTML }) {
  const containerAtual = document.querySelector('[data-transition="container"]');
  const wrapper = document.querySelector('[data-transition="wrapper"]');

  // Clonar o container para o próximo página
  const proximoContainer = containerAtual.cloneNode(true);
  const conteudo = document.createElement("main");
  conteudo.id = "page_content";
  conteudo.className = "page_content";
  conteudo.innerHTML = proximoHTML;
  proximoContainer.appendChild(conteudo);

  // Adicionar o próximo página ao DOM
  wrapper.appendChild(proximoContainer);

  // Executar a animação de transição
  const timeline = transicaoPadrao(containerAtual, proximoContainer);
  await timeline.finished;

  // Limpar o ambiente
  containerAtual.remove();
  gsap.set(proximoContainer, { clearProps: "all" });
}

Para implementar a lógica de transição assíncrona, criamos uma função chamada `executarTransicao`. Essa função é responsável por executar a transição entre as páginas.





async function executarTransicao(caminho) {
  // Bloquear a execução se uma transição estiver em andamento
  if (this.estaTransicionando) return;
  this.estaTransicionando = true;

  try {
    // Resolver a rota correspondente
    const rota = rotas[caminho];

    // Executar a transição assíncrona
    await executarTransicaoAssincrona({
      proximoHTML: moduloPagina.default(),
    });

    // Atualizar o namespace atual
    this.namespaceAtual = rota.namespace;
  } finally {
    // Liberar o bloqueio de transição
    this.estaTransicionando = false;
  }
}

Agora que temos a lógica de transição assíncrona implementada, podemos atualizar a função `navegar` para usar a `executarTransicao` em vez de executar a transição diretamente.


async function navegar(caminho) {
  if (window.location.pathname === caminho || this.estaTransicionando) return;
  window.history.pushState({}, "", caminho);
  await this.executarTransicao(caminho);
}

Com a lógica de transição assíncrona implementada, podemos agora adicionar uma animação de entrada para dar mais profundidade à transição.

Adicionando Animação de Entrada


import { gsap } from "../lib/index.js";
const ENTRADA = (proximoContainer, atraso) => {
  const titulo = proximoContainer?.querySelector("h1");
  if (!titulo) return null;
  gsap.set(titulo, { y: "100%" });
  const timeline = gsap.timeline({
    delay: atraso, 
  });
  timeline.to(titulo, {
    y: 0,
    duration: 1.2,
    force3D: true,
    ease: "expo.out",
  }, 0);
  return { timeline };
};
export default ENTRADA;

Para adicionar a animação de entrada, precisamos chamar a função `ENTRADA` dentro da função `iniciar` de cada página.


export function iniciar({ container }) {
  console.log(container);
}

Agora que temos a animação de entrada adicionada, podemos atualizar a função `executarTransicao` para chamar a função `iniciar` do próximo página.


export async function executarTransicao({ proximoHTML, proximoModulo }) {
  // ...

  if (proximoModulo && proximoModulo.iniciar) {
    proximoModulo.iniciar({ container: proximoContainer });
  }

  // ...
}

Integração e Funcionamento

O roteador e o motor de transição se integram para fornecer uma experiência de usuário suave e atraente. O roteador gerencia a navegação entre as páginas, enquanto o motor de transição cria as transições animadas entre as páginas.

Como funciona o sistema de transição de página

O sistema de transição de página funciona da seguinte maneira:

1. O roteador intercepta as requisições de navegação e atualiza a URL do navegador.
2. O motor de transição é chamado para criar a transição animada entre as páginas.
3. O motor de transição cria uma cópia da página atual e injeta a página nova na cópia.
4. O motor de transição anima a transição entre as duas páginas, criando uma transição suave e atraente.
5. Após a transição ser concluída, o motor de transição remove a página anterior e atualiza a página atual.

Código fonte


// Em roteador.js
async function executarTransicao(caminho) {
  // ...
  await executarTransicao({
    proximoHTML: moduloPagina.default(),
  });
  // ...
}

// Em transicaoPagina.js
export async function executarTransicao({ proximoHTML }) {
  const containerAtual = document.querySelector('[data-transition="container"]');
  const wrapper = document.querySelector('[data-transition="wrapper"]');
  const proximoContainer = wrapper.cloneNode(true);
  proximoContainer.innerHTML = proximoHTML;
  // ...
  const timeline = transicaoPadrao(containerAtual, proximoContainer);
  await timeline.finished;
  // ...
}

Integração com o roteador

O motor de transição é chamado pelo roteador para criar as transições animadas entre as páginas. O roteador atualiza a URL do navegador e chama o motor de transição para criar a transição animada.


// Em roteador.js
async function navegar(caminho) {
  try {
    await this.executarTransicao(caminho);
  } catch (erro) {
    // Tratamento de erro
  }
}

Integração com o motor de transição

O motor de transição é responsável por criar as transições animadas entre as páginas. Ele cria uma cópia da página atual, injeta a página nova na cópia e anima a transição entre as duas páginas.


// Em transicaoPagina.js
export async function executarTransicao({ proximoHTML }) {
  // ...
  const timeline = transicaoPadrao(containerAtual, proximoContainer);
  await timeline.finished;
  // ...
}

Fonte de Referência: tympanus.net.
Curadoria e Adaptação: Redação Yassutaro Developers.



Redação YTI&W-News

Redação Developers | Yassutaro TI & Web

Notícias do universo do Desenvolvimento Web, dicas e tutoriais para Webmasters.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Publicado em:Desenvolvimento Web
Fale Conosco
×

Inscreva-se em nossa Newsletter!


Receba nossos lançamentos e artigos em primera mão!