Esta é uma solução completa e otimizada para o projeto Animais Fantásticos da Origamid, refatorada utilizando as melhores práticas do Frontend Mentor. O projeto consiste em uma plataforma rica em interações com o usuário e consumo de APIs externas para exibição de dados biológicos e financeiros.
O objetivo deste projeto foi transformar uma estrutura funcional imperativa de JavaScript em uma arquitetura moderna baseada em Classes ES6 reutilizáveis e encapsuladas. O sistema gerencia simultaneamente componentes de interface, animações baseadas no scroll do usuário e o consumo assíncrono de dados externos, mantendo a performance otimizada através de debouncing.
Os usuários devem ser capazes de:
- Navegar de forma suave pelas seções através de âncoras internas.
- Alternar descrições visuais de espécies animais através de navegação por abas tabulares.
- Expandir e recolher perguntas frequentes por meio de um sistema de Accordion.
- Abrir e fechar janelas modais de login e visualizar mensagens flutuantes (tooltips) de endereço.
- Visualizar contadores numéricos animados automaticamente no momento em que a seção de dados entra na tela.
- Interagir com um carrossel de slides responsivo com suporte a arrastar (mouse) e toque (touch).
- Verificar o status de funcionamento do estabelecimento (Aberto/Fechado) calculado dinamicamente com base no fuso horário local e horário do sistema.
- Código no GitHub: https://github.com/danilo-guimaraes/animais-fantasticos
- Site ao vivo (Live Preview): https://danilo-guimaraes.github.io/animais-fantasticos/
- Arquitetura modular por Classes: Todo o comportamento de componentes como
ScrollSuave,Accordion,TabNav,ModaleTooltipfoi isolado em classes ES6 com herança e vinculação estrita de escopo (bind(this)). - Consumo de APIs Assíncronas (Async/Await): Requisições externas para carregar dinamicamente o censo populacional de animais via JSON local (
fetchAnimais) e a cotação em tempo real de doações de Bitcoin via Blockchain API (fetchBitcoin). - Otimização de Renderização: Implementação de técnica de
debouncepara evitar que disparos excessivos de eventos do tiposcrollouresizedegradem a taxa de quadros (FPS) do navegador. - Observadores de Mutação e Interseção: Uso de
MutationObserverpara monitorar alterações na árvore do DOM e disparar animações numéricas apenas quando as classes de ativação corretas forem injetadas no elemento alvo.
- HTML5 – Estrutura semântica das seções e controle de atributos customizados (
data-attributes). - Tailwind CSS v4 – Estilização utilitária avançada e configurações customizadas de gradientes radiais, paleta de cores (
sand,ink,ember) e sombras volumétricas. - JavaScript (ES6+) – Desenvolvimento orientado a objetos baseado em módulos e manipulação assíncrona do DOM.
- Webpack & Babel – Automação e compilação do código moderno em um único bundle unificado (
main.js) compatível com navegadores antigos através de polyfills de runtime. - ESLint – Padronização estrita de regras de formatação de código (espaçamentos, indentação em 2 espaços e uso obrigatório de ponto e vírgula).
A construção deste projeto solidificou habilidades críticas no desenvolvimento de aplicações JavaScript robustas e escaláveis, reduzindo a necessidade de bibliotecas terceiras de efeitos visuais:
- Garantia de Escopo em Manipulação de Eventos: Compreendi a importância de usar
this.bind(this)nos métodos que servem como callbacks de eventos para garantir que o escopo interno da função aponte sempre para a instância da classe criada, e não para o elemento que disparou o gatilho no DOM. - Separação de Métodos Estáticos: Entendi o momento ideal para declarar um método como
static, aplicando-o na lógica de incremento numérico incremental isolada, que não depende de variáveis de instância internas. - Gerenciamento Seguro de Cliques Externos: Criação de rotinas para fechar menus suspensos (
DropdownMenu) e navegáveis móveis apenas quando o usuário clica em elementos externos ao componente ativo, prevenindo loops de eventos através de delegação assíncrona comsetTimeout.
export default class Accordion {
constructor(list) {
this.accordionList = document.querySelectorAll(list);
this.activeClass = 'ativo';
}
toggleAccordion(item) {
item.classList.toggle(this.activeClass);
item.nextElementSibling.classList.toggle(this.activeClass);
}
addAccordionEvent() {
this.accordionList.forEach((item) => {
item.addEventListener('click', () => this.toggleAccordion(item));
});
}
init() {
if (this.accordionList.length) {
this.toggleAccordion(this.accordionList[0]);
this.addAccordionEvent();
}
return this;
}
}