📖 Glossário - Visualização Web

A

API (Application Programming Interface): Interface que permite comunicação entre sistemas/aplicações.

AJAX (Asynchronous JavaScript and XML): Técnica para atualizar partes de página sem recarregar.

Atributo HTML: Informação adicional em tag HTML (ex: class="container").

B

Bootstrap: Framework CSS popular para design responsivo.

Browser (Navegador): Software para acessar páginas web (Chrome, Firefox, Edge).

C

Canvas: Elemento HTML5 para desenho gráfico com JavaScript.

Cascata (CSS Cascade): Mecanismo que resolve conflitos entre regras CSS.

CDN (Content Delivery Network): Rede de servidores para entregar recursos web rapidamente.

Class (Classe CSS): Seletor reutilizável para estilizar múltiplos elementos.

Console: Ferramenta do navegador para debugar JavaScript (F12).

CSS (Cascading Style Sheets): Linguagem para estilizar páginas HTML.

D

Dev Tools (Ferramentas de Desenvolvimento): Conjunto de ferramentas no navegador para depuração (F12).

DIV: Elemento HTML genérico para agrupar conteúdo.

DOM (Document Object Model): Representação em árvore de documento HTML que JavaScript pode manipular.

Deploy: Processo de publicar aplicação na web.

E

Elemento: Unidade básica de HTML delimitada por tags (<tag>conteúdo</tag>).

Evento: Ação que ocorre na página (click, hover, load).

Event Listener: Função JavaScript que "escuta" eventos.

F

Flexbox: Sistema CSS para layout flexível e responsivo.

Folium: Biblioteca Python para criar mapas interativos Leaflet.

Framework: Conjunto de ferramentas e padrões para desenvolvimento.

Frontend: Parte da aplicação que usuário vê e interage.

G

GeoJSON Layer: Camada Leaflet para exibir dados GeoJSON.

Git: Sistema de controle de versão.

GitHub: Plataforma web para hospedar repositórios Git.

GitHub Pages: Serviço gratuito do GitHub para hospedar sites estáticos.

H

HTML (HyperText Markup Language): Linguagem de marcação para estruturar páginas web.

HTML5: Versão mais recente do HTML com novos elementos (video, canvas, etc).

HTTP/HTTPS: Protocolos de comunicação da web (HTTPS é seguro).

I

ID (Identificador): Atributo HTML único para elemento (id="mapa").

Inline Style: Estilo CSS aplicado diretamente no atributo style="".

Inspetor: Ferramenta do navegador para ver/editar HTML e CSS.

J

JavaScript (JS): Linguagem de programação para interatividade web.

jQuery: Biblioteca JavaScript para simplificar manipulação DOM (menos usada hoje).

JSON (JavaScript Object Notation): Formato de dados estruturados em texto.

L

Layer (Camada): Conjunto de elementos visuais em mapa (marcadores, polígonos).

Leaflet: Biblioteca JavaScript para mapas interativos.

Link: Elemento HTML para vincular recursos (<link> para CSS, <a> para hiperlinks).

M

Marcação (Markup): Código que estrutura conteúdo (HTML é linguagem de marcação).

Marcador (Marker): Ícone que indica ponto no mapa Leaflet.

Mapa Base (Base Layer): Camada de fundo do mapa (satélite, ruas, terreno).

Media Query: Regra CSS que aplica estilos baseado em tamanho de tela.

N

Node.js: Ambiente JavaScript fora do navegador.

npm: Gerenciador de pacotes JavaScript.

O

OpenStreetMap: Projeto colaborativo de mapa mundial livre.

Overlay: Camada sobreposta ao mapa base.

P

Popup: Janela informativa que aparece ao clicar em marcador/área.

Python Web Server: Servidor simples para testar páginas localmente.

Q

Query Selector: Método JavaScript para selecionar elementos (querySelector('#id')).

R

Repositório: Pasta de projeto com histórico Git.

Responsivo: Design que se adapta a diferentes tamanhos de tela.

S

Script: Código JavaScript em página HTML (<script>).

Seletor CSS: Padrão para identificar elementos (.class, #id, tag).

Semantic HTML: Uso de tags HTML que descrevem significado do conteúdo (<header>, <nav>, <article>).

Servidor Web: Software que entrega páginas web ao navegador.

SEO (Search Engine Optimization): Otimização para mecanismos de busca.

SPA (Single Page Application): Aplicação web que carrega uma página e atualiza dinamicamente.

T

Tag: Marcador HTML que define elemento (<tag>).

Template: Modelo/padrão de documento HTML.

Tile Layer: Camada de mapa composta por ladrilhos de imagens.

U

URL (Uniform Resource Locator): Endereço de recurso na web.

User Agent: Identificação do navegador do usuário.

V

Validação HTML: Processo de verificar se HTML está correto.

var/let/const: Formas de declarar variáveis em JavaScript.

ViewPort: Área visível da página no navegador.

W

Web Mapping: Criação e visualização de mapas interativos na web.

Webhook: URL que recebe notificações automáticas.

X

XMLHttpRequest: API para fazer requisições HTTP em JavaScript (substituída por fetch()).

Exemplos Práticos

HTML5 Básico

<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Meu Mapa</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <header>
        <h1>Monitoramento Costeiro</h1>
    </header>

    <main>
        <div id="mapa"></div>
    </main>

    <script src="app.js"></script>
</body>
</html>

JavaScript Essencial

// Selecionar elemento
const mapa = document.getElementById('mapa');

// Criar elemento
const marker = document.createElement('div');
marker.className = 'marker';
marker.textContent = 'Local';

// Adicionar à página
mapa.appendChild(marker);

// Escutar evento
marker.addEventListener('click', function() {
    alert('Você clicou no marcador!');
});

// Fetch de dados
fetch('dados.json')
    .then(response => response.json())
    .then(dados => {
        console.log(dados);
    });

Mapa Leaflet

// Criar mapa
var mapa = L.map('mapa').setView([-27.5, -48.5], 10);

// Adicionar camada base
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '© OpenStreetMap'
}).addTo(mapa);

// Adicionar marcador
L.marker([-27.43, -48.45])
    .addTo(mapa)
    .bindPopup('Praia dos Ingleses');

// Adicionar GeoJSON
fetch('pontos.geojson')
    .then(response => response.json())
    .then(dados => {
        L.geoJSON(dados).addTo(mapa);
    });

CSS Responsivo

/* Estilos base */
#mapa {
    width: 100%;
    height: 500px;
}

/* Mobile */
@media (max-width: 768px) {
    #mapa {
        height: 300px;
    }
}

/* Desktop */
@media (min-width: 1024px) {
    #mapa {
        height: 700px;
    }
}

Recursos Úteis

Ferramenta Uso URL
Leaflet Mapas interativos leafletjs.com
OpenStreetMap Mapa base livre openstreetmap.org
GitHub Pages Hospedar site pages.github.com
MDN Web Docs Documentação web developer.mozilla.org

💡 Dica: Use sempre <!DOCTYPE html> no início do arquivo HTML5!

🌐 HTML5 Básico - Criar Páginas Web

O que é HTML?

HTML (HyperText Markup Language) = linguagem de marcação para criar páginas web.

HTML        → Estrutura (conteúdo)
CSS         → Aparência (estilo)
JavaScript  → Comportamento (interação)

Analogia: - HTML = Esqueleto de uma casa - CSS = Pintura e decoração - JavaScript = Eletricidade e encanamento


📝 Estrutura Básica de HTML

Documento Mínimo

Crie arquivo pagina.html:

<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Minha Primeira Página</title>
</head>
<body>
    <h1>Olá, Mundo!</h1>
    <p>Esta é minha primeira página web.</p>
</body>
</html>

Abra no navegador (duplo clique ou arrastar para o navegador)!

Anatomia de uma Tag

<tagname atributo="valor">Conteúdo</tagname>
   ↑        ↑        ↑         ↑           ↑
 abertura  atrib   valor   conteúdo    fechamento

📋 Tags Essenciais

Cabeçalhos (Títulos)

<h1>Título Principal</h1>
<h2>Subtítulo</h2>
<h3>Seção</h3>
<h4>Subseção</h4>
<h5>Menor</h5>
<h6>Mínimo</h6>

Parágrafos e Texto

<p>Este é um parágrafo.</p>
<p>Este é outro parágrafo.</p>

<strong>Texto em negrito</strong>
<em>Texto em itálico</em>
<u>Texto sublinhado</u>
<br>  <!-- Quebra de linha -->
<hr>  <!-- Linha horizontal -->

Listas

<!-- Lista não ordenada (bullet points) -->
<ul>
    <li>Ulva lactuca</li>
    <li>Gracilaria</li>
    <li>Sargassum</li>
</ul>

<!-- Lista ordenada (numerada) -->
<ol>
    <li>Coletar amostra</li>
    <li>Identificar espécie</li>
    <li>Registrar dados</li>
</ol>
<!-- Link externo -->
<a href="https://www.ufsc.br">Visite a UFSC</a>

<!-- Link em nova aba -->
<a href="https://www.ufsc.br" target="_blank">UFSC (nova aba)</a>

<!-- Link para email -->
<a href="mailto:contato@LAFIC.ufsc.br">Enviar email</a>

Imagens

<img src="macroalga.jpg" alt="Ulva lactuca" width="400">

<!-- Com legenda -->
<figure>
    <img src="macroalga.jpg" alt="Ulva lactuca" width="400">
    <figcaption>Figura 1: Ulva lactuca coletada em Ingleses</figcaption>
</figure>

📊 Tabelas

<table border="1">
    <thead>
        <tr>
            <th>Espécie</th>
            <th>Profundidade (m)</th>
            <th>Temperatura (°C)</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Ulva lactuca</td>
            <td>5.2</td>
            <td>22.5</td>
        </tr>
        <tr>
            <td>Gracilaria</td>
            <td>7.8</td>
            <td>23.1</td>
        </tr>
        <tr>
            <td>Sargassum</td>
            <td>3.1</td>
            <td>22.8</td>
        </tr>
    </tbody>
</table>

🎨 CSS Básico (Estilo)

CSS Inline (dentro da tag)

<p style="color: blue; font-size: 20px;">Texto azul e grande</p>

CSS no <head> (interno)

<!DOCTYPE html>
<html>
<head>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
            background-color: #f0f8ff;
        }

        h1 {
            color: #2E86AB;
            text-align: center;
        }

        .destaque {
            background-color: yellow;
            padding: 10px;
        }
    </style>
</head>
<body>
    <h1>LAFIC - UFSC</h1>
    <p class="destaque">Texto destacado</p>
</body>
</html>

CSS Externo (arquivo separado)

Crie estilos.css:

body {
    font-family: Arial, sans-serif;
    margin: 20px;
}

h1 {
    color: #2E86AB;
}

.tabela-dados {
    border-collapse: collapse;
    width: 100%;
}

.tabela-dados th, .tabela-dados td {
    border: 1px solid #ddd;
    padding: 8px;
    text-align: left;
}

.tabela-dados th {
    background-color: #2E86AB;
    color: white;
}

No HTML:

<head>
    <link rel="stylesheet" href="estilos.css">
</head>

🎯 Exemplo Prático: Relatório de Coleta

Crie relatorio_coleta.html:

<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Relatório de Coleta - LAFIC</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            max-width: 900px;
            margin: 0 auto;
            padding: 20px;
            background-color: #f5f5f5;
        }

        header {
            background-color: #2E86AB;
            color: white;
            padding: 20px;
            text-align: center;
            border-radius: 8px;
            margin-bottom: 20px;
        }

        .secao {
            background-color: white;
            padding: 20px;
            margin-bottom: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }

        h2 {
            color: #2E86AB;
            border-bottom: 2px solid #2E86AB;
            padding-bottom: 10px;
        }

        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 15px;
        }

        th, td {
            padding: 12px;
            text-align: left;
            border-bottom: 1px solid #ddd;
        }

        th {
            background-color: #2E86AB;
            color: white;
        }

        tr:hover {
            background-color: #f5f5f5;
        }

        .badge {
            display: inline-block;
            padding: 5px 10px;
            border-radius: 4px;
            font-size: 12px;
            font-weight: bold;
        }

        .badge-valida {
            background-color: #28a745;
            color: white;
        }

        .badge-invalida {
            background-color: #dc3545;
            color: white;
        }

        .estatisticas {
            display: flex;
            justify-content: space-around;
            margin-top: 20px;
        }

        .stat-box {
            text-align: center;
            padding: 15px;
            background-color: #e7f3f8;
            border-radius: 8px;
            flex: 1;
            margin: 0 10px;
        }

        .stat-numero {
            font-size: 36px;
            font-weight: bold;
            color: #2E86AB;
        }

        .stat-label {
            font-size: 14px;
            color: #666;
        }
    </style>
</head>
<body>
    <header>
        <h1>🌊 Relatório de Coleta de Macroalgas</h1>
        <p>LAFIC - Laboratório de Ficologia (LAFIC) / UFSC</p>
        <p>Data: 06 de Janeiro de 2025</p>
    </header>

    <div class="secao">
        <h2>📊 Estatísticas Gerais</h2>
        <div class="estatisticas">
            <div class="stat-box">
                <div class="stat-numero">10</div>
                <div class="stat-label">Total de Coletas</div>
            </div>
            <div class="stat-box">
                <div class="stat-numero">4</div>
                <div class="stat-label">Espécies Identificadas</div>
            </div>
            <div class="stat-box">
                <div class="stat-numero">22.7°C</div>
                <div class="stat-label">Temperatura Média</div>
            </div>
            <div class="stat-box">
                <div class="stat-numero">6.8m</div>
                <div class="stat-label">Profundidade Média</div>
            </div>
        </div>
    </div>

    <div class="secao">
        <h2>🗺️ Locais de Coleta</h2>
        <table>
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Local</th>
                    <th>Espécie</th>
                    <th>Profundidade</th>
                    <th>Temperatura</th>
                    <th>Status</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>1</td>
                    <td>Ingleses Norte</td>
                    <td><em>Ulva lactuca</em></td>
                    <td>5.2m</td>
                    <td>22.5°C</td>
                    <td><span class="badge badge-valida">✓ VÁLIDA</span></td>
                </tr>
                <tr>
                    <td>2</td>
                    <td>Ingleses Sul</td>
                    <td><em>Gracilaria</em></td>
                    <td>7.8m</td>
                    <td>23.1°C</td>
                    <td><span class="badge badge-valida">✓ VÁLIDA</span></td>
                </tr>
                <tr>
                    <td>3</td>
                    <td>Barra da Lagoa</td>
                    <td><em>Sargassum</em></td>
                    <td>3.1m</td>
                    <td>22.8°C</td>
                    <td><span class="badge badge-valida">✓ VÁLIDA</span></td>
                </tr>
                <tr>
                    <td>4</td>
                    <td>Laguna</td>
                    <td><em>Laminaria</em></td>
                    <td>10.5m</td>
                    <td>21.2°C</td>
                    <td><span class="badge badge-invalida">✗ ATENÇÃO</span></td>
                </tr>
            </tbody>
        </table>
    </div>

    <div class="secao">
        <h2>🌿 Espécies Coletadas</h2>
        <ul>
            <li><strong>Ulva lactuca</strong> - 4 amostras (40%)</li>
            <li><strong>Gracilaria</strong> - 3 amostras (30%)</li>
            <li><strong>Sargassum</strong> - 2 amostras (20%)</li>
            <li><strong>Laminaria</strong> - 1 amostra (10%)</li>
        </ul>
    </div>

    <div class="secao">
        <h2>📝 Observações</h2>
        <p>
            As coletas foram realizadas em condições favoráveis, com mar calmo e 
            visibilidade adequada. A maioria das amostras (90%) foi validada de acordo 
            com os parâmetros estabelecidos (temperatura entre 20-25°C, profundidade 
            menor que 10m).
        </p>
        <p>
            A espécie <em>Ulva lactuca</em> foi predominante na região de Ingleses, 
            corroborando estudos anteriores sobre sua distribuição na costa catarinense.
        </p>
    </div>

    <footer style="text-align: center; padding: 20px; color: #666;">
        <p>
            <strong>LAFIC - Laboratório de Ficologia (LAFIC)</strong><br>
            Departamento de Botânica - UFSC<br>
            Florianópolis, Santa Catarina, Brasil
        </p>
    </footer>
</body>
</html>

Abra no navegador! Você verá um relatório profissional! 📊


📱 Design Responsivo

Fazer a página se adaptar a diferentes tamanhos de tela:

<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        /* Desktop */
        .container {
            display: flex;
            gap: 20px;
        }

        .coluna {
            flex: 1;
        }

        /* Mobile (telas menores que 768px) */
        @media (max-width: 768px) {
            .container {
                flex-direction: column;
            }
        }
    </style>
</head>

🎓 Formulários

Coletar dados do usuário:

<form action="/processar" method="POST">
    <label for="especie">Espécie:</label>
    <input type="text" id="especie" name="especie" required>

    <label for="profundidade">Profundidade (m):</label>
    <input type="number" id="profundidade" name="profundidade" step="0.1" required>

    <label for="temperatura">Temperatura (°C):</label>
    <input type="number" id="temperatura" name="temperatura" step="0.1" required>

    <label for="local">Local:</label>
    <select id="local" name="local">
        <option value="ingleses">Praia dos Ingleses</option>
        <option value="laguna">Laguna</option>
        <option value="garopaba">Garopaba</option>
    </select>

    <label for="observacoes">Observações:</label>
    <textarea id="observacoes" name="observacoes" rows="4"></textarea>

    <button type="submit">Enviar</button>
</form>

🎓 Checklist desta Lição

  • [ ] Entendo a estrutura básica de HTML
  • [ ] Conheço as principais tags
  • [ ] Criei uma tabela HTML
  • [ ] Apliquei CSS básico
  • [ ] Criei um relatório formatado
  • [ ] Testei no navegador

Se marcou tudo, você está pronto para JavaScript! 🎉


➡️ Próximo Tópico

👉 02-JavaScript-Essencial.html

Lá você aprenderá: - Sintaxe JavaScript - Manipular elementos HTML - Interatividade - Processar dados


📝 Resumo de Tags

Tag Uso
<h1>-<h6> Títulos
<p> Parágrafo
<a> Link
<img> Imagem
<table> Tabela
<ul>/<ol> Listas
<div> Container genérico
<span> Texto inline

Você criou sua primeira página web! 🌐 Próximo: JavaScript para interatividade! ⚡

⚡ JavaScript Essencial - Interatividade Web

O que é JavaScript?

JavaScript = linguagem de programação para web (navegadores).

HTML       → Conteúdo estático
CSS        → Aparência estática
JavaScript → Comportamento dinâmico

JavaScript faz: - Responder a cliques - Validar formulários - Processar dados - Atualizar conteúdo sem recarregar página - Criar animações


📝 Adicionar JavaScript ao HTML

Método 1: Inline (dentro de tag)

<button onclick="alert('Olá!')">Clique Aqui</button>

Método 2: No <script> interno

<!DOCTYPE html>
<html>
<head>
    <title>Minha Página</title>
</head>
<body>
    <h1 id="titulo">LAFIC</h1>
    <button onclick="mudarTitulo()">Mudar Título</button>

    <script>
        function mudarTitulo() {
            document.getElementById('titulo').textContent = 'Oceanografia UFSC';
        }
    </script>
</body>
</html>

Método 3: Arquivo externo (RECOMENDADO)

Crie script.js:

function mudarTitulo() {
    document.getElementById('titulo').textContent = 'Oceanografia UFSC';
}

No HTML:

<body>
    <h1 id="titulo">LAFIC</h1>
    <button onclick="mudarTitulo()">Mudar Título</button>

    <script src="script.js"></script>
</body>

🔤 Sintaxe Básica

Variáveis

// var (antigo - evitar)
var nome = "Caetano";

// let (moderno - pode mudar)
let temperatura = 22.5;
temperatura = 23.0;  // OK

// const (constante - não muda)
const PI = 3.14159;
// PI = 3.14;  // ERRO!

Tipos de Dados

// String (texto)
let especie = "Ulva lactuca";
let local = 'Ingleses';  // aspas simples ou duplas

// Number (número)
let profundidade = 5.2;
let quantidade = 10;

// Boolean (verdadeiro/falso)
let valida = true;
let coletada = false;

// Array (lista)
let especies = ["Ulva", "Gracilaria", "Sargassum"];
let temperaturas = [22.5, 23.1, 22.8];

// Object (objeto)
let amostra = {
    especie: "Ulva lactuca",
    profundidade: 5.2,
    temperatura: 22.5,
    valida: true
};

Operadores

// Aritméticos
let soma = 10 + 5;          // 15
let subtracao = 10 - 5;     // 5
let multiplicacao = 10 * 5; // 50
let divisao = 10 / 5;       // 2
let resto = 10 % 3;         // 1

// Comparação
console.log(10 == "10");    // true (valor igual)
console.log(10 === "10");   // false (valor E tipo iguais)
console.log(10 != 5);       // true
console.log(10 > 5);        // true

// Lógicos
console.log(true && false); // false (E)
console.log(true || false); // true (OU)
console.log(!true);         // false (NÃO)

🔧 Funções

// Função simples
function saudar() {
    console.log("Olá, LAFIC!");
}

saudar();  // Chamar função

// Função com parâmetros
function calcularMedia(a, b, c) {
    return (a + b + c) / 3;
}

let media = calcularMedia(22.5, 23.1, 22.8);
console.log(media);  // 22.8

// Arrow function (moderna)
const quadrado = (x) => x * x;
console.log(quadrado(5));  // 25

// Função com objeto
function validarAmostra(temp, prof) {
    if (temp >= 20 && temp <= 25 && prof < 10) {
        return { valida: true, mensagem: "✓ VÁLIDA" };
    } else {
        return { valida: false, mensagem: "✗ INVÁLIDA" };
    }
}

let resultado = validarAmostra(22.5, 5.2);
console.log(resultado.mensagem);  // "✓ VÁLIDA"

🎯 Manipular o DOM (Document Object Model)

DOM = representação da página HTML que JavaScript pode modificar.

Selecionar Elementos

// Por ID
let titulo = document.getElementById('titulo');

// Por classe
let elementos = document.getElementsByClassName('destaque');

// Por tag
let paragrafos = document.getElementsByTagName('p');

// Query Selector (moderno - mais flexível)
let primeiroP = document.querySelector('p');
let todosP = document.querySelectorAll('p');

Modificar Conteúdo

// Alterar texto
document.getElementById('titulo').textContent = 'Novo Título';

// Alterar HTML
document.getElementById('container').innerHTML = '<p>Novo parágrafo</p>';

// Alterar atributos
let imagem = document.getElementById('foto');
imagem.src = 'nova_foto.jpg';
imagem.alt = 'Nova descrição';

Modificar Estilo

let elemento = document.getElementById('caixa');

// Alterar CSS
elemento.style.color = 'blue';
elemento.style.backgroundColor = '#f0f0f0';
elemento.style.fontSize = '20px';
elemento.style.display = 'none';  // Esconder

// Adicionar/remover classe
elemento.classList.add('destaque');
elemento.classList.remove('destaque');
elemento.classList.toggle('ativo');  // Alterna

🖱️ Eventos (Interatividade)

Click

// Método 1: HTML
<button onclick="minhaFuncao()">Clique</button>

// Método 2: JavaScript (RECOMENDADO)
document.getElementById('botao').addEventListener('click', function() {
    alert('Botão clicado!');
});

// Método 3: Arrow function
document.getElementById('botao').addEventListener('click', () => {
    alert('Botão clicado!');
});

Outros Eventos

// Mouse
elemento.addEventListener('mouseover', () => {
    console.log('Mouse em cima');
});

elemento.addEventListener('mouseout', () => {
    console.log('Mouse saiu');
});

// Teclado
input.addEventListener('keyup', (event) => {
    console.log('Tecla pressionada:', event.key);
});

// Formulário
formulario.addEventListener('submit', (event) => {
    event.preventDefault();  // Evitar envio padrão
    console.log('Formulário enviado');
});

// Página carregada
document.addEventListener('DOMContentLoaded', () => {
    console.log('Página carregada!');
});

📊 Trabalhar com Arrays

let especies = ["Ulva", "Gracilaria", "Sargassum"];

// Acessar
console.log(especies[0]);  // "Ulva"

// Adicionar
especies.push("Laminaria");  // Adiciona no final
especies.unshift("Codium");  // Adiciona no início

// Remover
let ultimo = especies.pop();     // Remove e retorna último
let primeiro = especies.shift(); // Remove e retorna primeiro

// Tamanho
console.log(especies.length);  // 3

// Iterar
especies.forEach((especie, index) => {
    console.log(`${index}: ${especie}`);
});

// Map (transformar)
let maiusculas = especies.map(e => e.toUpperCase());

// Filter (filtrar)
let comU = especies.filter(e => e.startsWith('U'));

// Find (encontrar)
let gracilaria = especies.find(e => e === 'Gracilaria');

🎯 Exemplo Prático 1: Calculadora Oceanográfica

Crie calculadora.html:

<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <title>Calculadora Oceanográfica</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 600px;
            margin: 50px auto;
            padding: 20px;
            background-color: #f0f8ff;
        }

        .container {
            background: white;
            padding: 30px;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }

        h1 {
            color: #2E86AB;
            text-align: center;
        }

        .form-group {
            margin-bottom: 15px;
        }

        label {
            display: block;
            margin-bottom: 5px;
            font-weight: bold;
        }

        input {
            width: 100%;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 5px;
            box-sizing: border-box;
        }

        button {
            width: 100%;
            padding: 12px;
            background-color: #2E86AB;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 16px;
        }

        button:hover {
            background-color: #236a8c;
        }

        #resultado {
            margin-top: 20px;
            padding: 15px;
            border-radius: 5px;
            display: none;
        }

        .valida {
            background-color: #d4edda;
            border: 1px solid #c3e6cb;
        }

        .invalida {
            background-color: #f8d7da;
            border: 1px solid #f5c6cb;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>🌊 Calculadora Oceanográfica</h1>

        <div class="form-group">
            <label for="profundidade">Profundidade (m):</label>
            <input type="number" id="profundidade" step="0.1" placeholder="Ex: 5.2">
        </div>

        <div class="form-group">
            <label for="temperatura">Temperatura (°C):</label>
            <input type="number" id="temperatura" step="0.1" placeholder="Ex: 22.5">
        </div>

        <div class="form-group">
            <label for="salinidade">Salinidade (PSU):</label>
            <input type="number" id="salinidade" step="0.1" placeholder="Ex: 35.0">
        </div>

        <button onclick="calcular()">Calcular</button>

        <div id="resultado"></div>
    </div>

    <script>
        function calcular() {
            // Obter valores
            const prof = parseFloat(document.getElementById('profundidade').value);
            const temp = parseFloat(document.getElementById('temperatura').value);
            const sal = parseFloat(document.getElementById('salinidade').value);

            // Validar entrada
            if (isNaN(prof) || isNaN(temp) || isNaN(sal)) {
                alert('Por favor, preencha todos os campos!');
                return;
            }

            // Cálculos
            const pressao = 1 + (prof / 10);  // 1 atm por 10m
            const densidade = 1000 + (sal - 35) * 0.78;  // Simplificado
            const luzPenetracao = 100 * Math.pow(0.7, prof / 10);

            // Validação
            const tempValida = temp >= 20 && temp <= 25;
            const salValida = sal >= 34 && sal <= 36;
            const profValida = prof < 50;
            const todasValidas = tempValida && salValida && profValida;

            // Montar resultado
            let html = `
                <h3>${todasValidas ? '✅' : '⚠️'} Resultados:</h3>
                <p><strong>Pressão:</strong> ${pressao.toFixed(2)} atm</p>
                <p><strong>Densidade:</strong> ${densidade.toFixed(2)} kg/m³</p>
                <p><strong>Penetração de Luz:</strong> ${luzPenetracao.toFixed(1)}%</p>
                <hr>
                <h4>Validação:</h4>
                <p>Temperatura: ${tempValida ? '✓' : '✗'} ${temp}°C</p>
                <p>Salinidade: ${salValida ? '✓' : '✗'} ${sal} PSU</p>
                <p>Profundidade: ${profValida ? '✓' : '✗'} ${prof}m</p>
                <hr>
                <p><strong>Status: ${todasValidas ? 'CONDIÇÕES IDEAIS' : 'ATENÇÃO AOS PARÂMETROS'}</strong></p>
            `;

            // Mostrar resultado
            const divResultado = document.getElementById('resultado');
            divResultado.innerHTML = html;
            divResultado.className = todasValidas ? 'valida' : 'invalida';
            divResultado.style.display = 'block';
        }

        // Permitir Enter para calcular
        document.addEventListener('keyup', (event) => {
            if (event.key === 'Enter') {
                calcular();
            }
        });
    </script>
</body>
</html>

Teste no navegador! 🧮


🎯 Exemplo Prático 2: Tabela Dinâmica de Coletas

Crie tabela_dinamica.html:

<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <title>Gerenciador de Coletas</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 900px;
            margin: 30px auto;
            padding: 20px;
        }

        h1 {
            color: #2E86AB;
        }

        .form-container {
            background: #f9f9f9;
            padding: 20px;
            border-radius: 8px;
            margin-bottom: 20px;
        }

        .form-grid {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 10px;
        }

        input, select {
            width: 100%;
            padding: 8px;
            border: 1px solid #ddd;
            border-radius: 4px;
        }

        button {
            padding: 10px 20px;
            background-color: #2E86AB;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            margin-top: 10px;
        }

        button:hover {
            background-color: #236a8c;
        }

        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 20px;
        }

        th, td {
            padding: 12px;
            text-align: left;
            border-bottom: 1px solid #ddd;
        }

        th {
            background-color: #2E86AB;
            color: white;
        }

        tr:hover {
            background-color: #f5f5f5;
        }

        .btn-remover {
            background-color: #dc3545;
            padding: 5px 10px;
            font-size: 12px;
        }
    </style>
</head>
<body>
    <h1>📊 Gerenciador de Coletas - LAFIC</h1>

    <div class="form-container">
        <h3>Adicionar Nova Coleta</h3>
        <div class="form-grid">
            <input type="text" id="local" placeholder="Local">
            <input type="text" id="especie" placeholder="Espécie">
            <input type="number" id="prof" step="0.1" placeholder="Profundidade (m)">
            <input type="number" id="temp" step="0.1" placeholder="Temperatura (°C)">
        </div>
        <button onclick="adicionarColeta()">➕ Adicionar Coleta</button>
    </div>

    <h3>Coletas Registradas: <span id="total">0</span></h3>
    <table id="tabela">
        <thead>
            <tr>
                <th>ID</th>
                <th>Local</th>
                <th>Espécie</th>
                <th>Profundidade</th>
                <th>Temperatura</th>
                <th>Status</th>
                <th>Ação</th>
            </tr>
        </thead>
        <tbody id="tbody">
        </tbody>
    </table>

    <script>
        let coletas = [];
        let proximoId = 1;

        function adicionarColeta() {
            // Obter valores
            const local = document.getElementById('local').value;
            const especie = document.getElementById('especie').value;
            const prof = parseFloat(document.getElementById('prof').value);
            const temp = parseFloat(document.getElementById('temp').value);

            // Validar
            if (!local || !especie || isNaN(prof) || isNaN(temp)) {
                alert('Preencha todos os campos!');
                return;
            }

            // Criar coleta
            const coleta = {
                id: proximoId++,
                local: local,
                especie: especie,
                profundidade: prof,
                temperatura: temp,
                valida: (temp >= 20 && temp <= 25 && prof < 10)
            };

            // Adicionar ao array
            coletas.push(coleta);

            // Limpar formulário
            document.getElementById('local').value = '';
            document.getElementById('especie').value = '';
            document.getElementById('prof').value = '';
            document.getElementById('temp').value = '';

            // Atualizar tabela
            atualizarTabela();
        }

        function removerColeta(id) {
            coletas = coletas.filter(c => c.id !== id);
            atualizarTabela();
        }

        function atualizarTabela() {
            const tbody = document.getElementById('tbody');
            tbody.innerHTML = '';

            coletas.forEach(coleta => {
                const tr = document.createElement('tr');

                const status = coleta.valida ? 
                    '<span style="color: green;">✓ VÁLIDA</span>' :
                    '<span style="color: red;">✗ ATENÇÃO</span>';

                tr.innerHTML = `
                    <td>${coleta.id}</td>
                    <td>${coleta.local}</td>
                    <td><em>${coleta.especie}</em></td>
                    <td>${coleta.profundidade.toFixed(1)}m</td>
                    <td>${coleta.temperatura.toFixed(1)}°C</td>
                    <td>${status}</td>
                    <td>
                        <button class="btn-remover" onclick="removerColeta(${coleta.id})">
                            🗑️ Remover
                        </button>
                    </td>
                `;

                tbody.appendChild(tr);
            });

            // Atualizar contador
            document.getElementById('total').textContent = coletas.length;
        }
    </script>
</body>
</html>

Teste adicionando e removendo coletas! ✨


🎓 Checklist desta Lição

  • [ ] Entendo sintaxe JavaScript básica
  • [ ] Consigo manipular o DOM
  • [ ] Sei trabalhar com eventos
  • [ ] Criei uma aplicação interativa
  • [ ] Testei no navegador

Se marcou tudo, você está pronto para Leaflet.js! 🎉


➡️ Próximo Tópico

👉 03-Leaflet-Mapas.html

Lá você aprenderá: - Criar mapas com Leaflet.js - Adicionar marcadores dinamicamente - Integrar com dados JavaScript - Criar dashboards completos


📝 Resumo de Conceitos

Conceito Descrição
DOM Representação da página HTML
Event Ação do usuário (click, etc)
querySelector Selecionar elementos
addEventListener Escutar eventos
innerHTML Modificar HTML
classList Manipular classes CSS

Você domina JavaScript básico! ⚡ Próximo: Mapas interativos com Leaflet! 🗺️

🗺️ Leaflet.js - Mapas Interativos com JavaScript

O que é Leaflet.js?

Leaflet = biblioteca JavaScript para criar mapas interativos na web.

Folium (Python)  → Gera HTML com Leaflet
Leaflet.js       → Controle total com JavaScript

Vantagens: - Leve e rápido - Open source - Funciona em mobile - Altamente customizável

Site oficial: https://leafletjs.com


🚀 Setup Básico

HTML com Leaflet

Crie mapa_leaflet.html:

<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mapa Leaflet - LAFIC</title>

    <!-- Leaflet CSS -->
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />

    <style>
        body {
            margin: 0;
            padding: 0;
            font-family: Arial, sans-serif;
        }

        #map {
            height: 600px;
            width: 100%;
        }
    </style>
</head>
<body>
    <div id="map"></div>

    <!-- Leaflet JavaScript -->
    <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>

    <script>
        // Criar mapa centrado em Florianópolis
        const map = L.map('map').setView([-27.5969, -48.5495], 12);

        // Adicionar camada de tiles (OpenStreetMap)
        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: '© OpenStreetMap contributors'
        }).addTo(map);

        // Adicionar marcador
        L.marker([-27.5969, -48.5495])
            .addTo(map)
            .bindPopup('UFSC - Florianópolis')
            .openPopup();
    </script>
</body>
</html>

Abra no navegador! Você verá um mapa interativo! 🗺️


📍 Marcadores (Markers)

Marcador Básico

// Criar marcador
const marcador = L.marker([-27.5969, -48.5495]).addTo(map);

// Com popup
marcador.bindPopup('UFSC');

// Com tooltip (aparece ao passar mouse)
marcador.bindTooltip('Campus Trindade');

Múltiplos Marcadores

const coletas = [
    { lat: -27.4374, lon: -48.3923, nome: "Ingleses Norte", especie: "Ulva lactuca" },
    { lat: -27.4450, lon: -48.3950, nome: "Ingleses Sul", especie: "Gracilaria" },
    { lat: -27.5750, lon: -48.4200, nome: "Barra da Lagoa", especie: "Sargassum" }
];

coletas.forEach(coleta => {
    L.marker([coleta.lat, coleta.lon])
        .addTo(map)
        .bindPopup(`<b>${coleta.nome}</b><br>${coleta.especie}`);
});

Ícones Personalizados

// Criar ícone customizado
const iconeVerde = L.icon({
    iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png',
    iconSize: [25, 41],
    iconAnchor: [12, 41],
    popupAnchor: [1, -34]
});

// Usar ícone
L.marker([-27.4374, -48.3923], { icon: iconeVerde })
    .addTo(map)
    .bindPopup('Ulva lactuca');

⭕ Círculos e Formas

Circle Markers

// Círculo proporcional a valor
const coletas = [
    { lat: -27.4374, lon: -48.3923, prof: 5.2 },
    { lat: -27.4450, lon: -48.3950, prof: 12.8 },
    { lat: -27.5750, lon: -48.4200, prof: 3.1 }
];

coletas.forEach(c => {
    L.circleMarker([c.lat, c.lon], {
        radius: c.prof * 2,  // Proporcional à profundidade
        color: 'blue',
        fillColor: '#30a3dc',
        fillOpacity: 0.6
    })
    .addTo(map)
    .bindPopup(`Profundidade: ${c.prof}m`);
});

Polígonos

// Área de estudo (polígono)
const areaEstudo = [
    [-27.55, -48.55],
    [-27.55, -48.50],
    [-27.60, -48.50],
    [-27.60, -48.55]
];

L.polygon(areaEstudo, {
    color: 'red',
    fillColor: '#ff0000',
    fillOpacity: 0.2
})
.addTo(map)
.bindPopup('Área de Proteção Marinha');

🎨 Popups HTML Avançados

const coleta = {
    id: 1,
    local: "Ingleses Norte",
    especie: "Ulva lactuca",
    prof: 5.2,
    temp: 22.5,
    sal: 35.0
};

const popupHTML = `
    <div style="font-family: Arial; min-width: 200px;">
        <h3 style="color: #2E86AB; margin-top: 0;">
            📍 ${coleta.local}
        </h3>
        <hr style="margin: 10px 0;">
        <table style="width: 100%; font-size: 14px;">
            <tr>
                <td><strong>ID:</strong></td>
                <td>${coleta.id}</td>
            </tr>
            <tr>
                <td><strong>Espécie:</strong></td>
                <td><em>${coleta.especie}</em></td>
            </tr>
            <tr>
                <td><strong>Profundidade:</strong></td>
                <td>${coleta.prof}m</td>
            </tr>
            <tr>
                <td><strong>Temperatura:</strong></td>
                <td>${coleta.temp}°C</td>
            </tr>
            <tr>
                <td><strong>Salinidade:</strong></td>
                <td>${coleta.sal} PSU</td>
            </tr>
        </table>
        <hr style="margin: 10px 0;">
        <button onclick="verDetalhes(${coleta.id})" 
                style="width: 100%; padding: 8px; background: #2E86AB; color: white; border: none; cursor: pointer; border-radius: 4px;">
            Ver Detalhes
        </button>
    </div>
`;

L.marker([coleta.lat, coleta.lon])
    .addTo(map)
    .bindPopup(popupHTML);

🗂️ Controle de Camadas

// Criar grupos de camadas
const grupoUlva = L.layerGroup();
const grupoGracilaria = L.layerGroup();
const grupoSargassum = L.layerGroup();

// Adicionar marcadores aos grupos
L.marker([-27.4374, -48.3923])
    .bindPopup('Ulva lactuca')
    .addTo(grupoUlva);

L.marker([-27.4450, -48.3950])
    .bindPopup('Gracilaria')
    .addTo(grupoGracilaria);

// Criar controle de camadas
const overlays = {
    "Ulva lactuca": grupoUlva,
    "Gracilaria": grupoGracilaria,
    "Sargassum": grupoSargassum
};

L.control.layers(null, overlays).addTo(map);

// Adicionar grupos ao mapa por padrão
grupoUlva.addTo(map);
grupoGracilaria.addTo(map);

🎯 Exemplo Completo: Dashboard Interativo

Crie dashboard_completo.html:

<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dashboard LAFIC</title>

    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />

    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }

        header {
            background: linear-gradient(135deg, #2E86AB 0%, #1a5c7a 100%);
            color: white;
            padding: 20px;
            text-align: center;
        }

        .container {
            display: flex;
            height: calc(100vh - 80px);
        }

        .sidebar {
            width: 300px;
            background: #f8f9fa;
            padding: 20px;
            overflow-y: auto;
            border-right: 1px solid #dee2e6;
        }

        #map {
            flex: 1;
        }

        .stat-card {
            background: white;
            padding: 15px;
            margin-bottom: 15px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }

        .stat-card h3 {
            color: #2E86AB;
            font-size: 14px;
            margin-bottom: 10px;
        }

        .stat-number {
            font-size: 32px;
            font-weight: bold;
            color: #333;
        }

        .species-list {
            list-style: none;
            margin-top: 10px;
        }

        .species-list li {
            padding: 8px;
            margin-bottom: 5px;
            background: white;
            border-radius: 4px;
            cursor: pointer;
            transition: background 0.3s;
        }

        .species-list li:hover {
            background: #e9ecef;
        }

        .badge {
            display: inline-block;
            padding: 3px 8px;
            border-radius: 12px;
            font-size: 11px;
            font-weight: bold;
        }

        .badge-green { background: #28a745; color: white; }
        .badge-red { background: #dc3545; color: white; }
        .badge-blue { background: #007bff; color: white; }
        .badge-yellow { background: #ffc107; color: white; }
    </style>
</head>
<body>
    <header>
        <h1>🌊 Dashboard de Coletas - LAFIC/UFSC</h1>
        <p>Monitoramento de Macroalgas na Costa de Santa Catarina</p>
    </header>

    <div class="container">
        <div class="sidebar">
            <div class="stat-card">
                <h3>📊 ESTATÍSTICAS GERAIS</h3>
                <div style="text-align: center;">
                    <div class="stat-number" id="totalColetas">0</div>
                    <div>Total de Coletas</div>
                </div>
            </div>

            <div class="stat-card">
                <h3>🌿 ESPÉCIES</h3>
                <ul class="species-list" id="especiesList"></ul>
            </div>

            <div class="stat-card">
                <h3>📈 MÉDIAS</h3>
                <div id="medias"></div>
            </div>
        </div>

        <div id="map"></div>
    </div>

    <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>

    <script>
        // Dados de coleta
        const coletas = [
            { id: 1, lat: -27.4374, lon: -48.3923, local: "Ingleses N", especie: "Ulva lactuca", prof: 5.2, temp: 22.5, sal: 35.0 },
            { id: 2, lat: -27.4450, lon: -48.3950, local: "Ingleses S", especie: "Gracilaria", prof: 7.8, temp: 23.1, sal: 34.8 },
            { id: 3, lat: -27.5750, lon: -48.4200, local: "Barra Lagoa", especie: "Sargassum", prof: 3.1, temp: 22.8, sal: 35.1 },
            { id: 4, lat: -28.4833, lon: -48.7833, local: "Laguna", especie: "Laminaria", prof: 10.5, temp: 21.2, sal: 35.0 },
            { id: 5, lat: -28.0200, lon: -48.6200, local: "Garopaba", especie: "Gracilaria", prof: 6.0, temp: 22.0, sal: 34.9 },
            { id: 6, lat: -27.7500, lon: -48.5100, local: "Armação", especie: "Ulva lactuca", prof: 4.5, temp: 23.5, sal: 35.1 }
        ];

        // Cores por espécie
        const coresEspecies = {
            "Ulva lactuca": "#28a745",
            "Gracilaria": "#dc3545",
            "Sargassum": "#007bff",
            "Laminaria": "#6f42c1"
        };

        // Criar mapa
        const map = L.map('map').setView([-27.8, -48.5], 9);

        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: '© OpenStreetMap'
        }).addTo(map);

        // Adicionar marcadores
        coletas.forEach(coleta => {
            const cor = coresEspecies[coleta.especie];
            const valida = (coleta.temp >= 20 && coleta.temp <= 25 && coleta.prof < 10);

            // Criar ícone SVG personalizado
            const iconeHTML = `
                <div style="background-color: ${cor}; width: 30px; height: 30px; 
                            border-radius: 50%; border: 3px solid white; 
                            box-shadow: 0 2px 4px rgba(0,0,0,0.3);
                            display: flex; align-items: center; justify-content: center;
                            color: white; font-weight: bold; font-size: 12px;">
                    ${coleta.id}
                </div>
            `;

            const icone = L.divIcon({
                html: iconeHTML,
                iconSize: [30, 30],
                className: ''
            });

            // Popup
            const popupHTML = `
                <div style="font-family: Arial; min-width: 220px;">
                    <h3 style="color: ${cor}; margin: 0 0 10px 0;">
                        📍 ${coleta.local}
                    </h3>
                    <hr style="margin: 10px 0; border: none; border-top: 1px solid #ddd;">
                    <table style="width: 100%; font-size: 13px;">
                        <tr><td><strong>ID:</strong></td><td>#${coleta.id}</td></tr>
                        <tr><td><strong>Espécie:</strong></td><td><em>${coleta.especie}</em></td></tr>
                        <tr><td><strong>Profundidade:</strong></td><td>${coleta.prof}m</td></tr>
                        <tr><td><strong>Temperatura:</strong></td><td>${coleta.temp}°C</td></tr>
                        <tr><td><strong>Salinidade:</strong></td><td>${coleta.sal} PSU</td></tr>
                    </table>
                    <hr style="margin: 10px 0; border: none; border-top: 1px solid #ddd;">
                    <div style="text-align: center; padding: 8px; background: ${valida ? '#d4edda' : '#fff3cd'}; border-radius: 4px;">
                        <strong>${valida ? '✅ VÁLIDA' : '⚠️ ATENÇÃO'}</strong>
                    </div>
                </div>
            `;

            L.marker([coleta.lat, coleta.lon], { icon: icone })
                .addTo(map)
                .bindPopup(popupHTML);
        });

        // Atualizar sidebar
        function atualizarEstatisticas() {
            // Total
            document.getElementById('totalColetas').textContent = coletas.length;

            // Espécies
            const especiesCount = {};
            coletas.forEach(c => {
                especiesCount[c.especie] = (especiesCount[c.especie] || 0) + 1;
            });

            const especiesList = document.getElementById('especiesList');
            especiesList.innerHTML = '';
            Object.entries(especiesCount).forEach(([especie, count]) => {
                const cor = coresEspecies[especie];
                const li = document.createElement('li');
                li.innerHTML = `
                    <span class="badge" style="background: ${cor};">${count}</span>
                    <em style="margin-left: 10px;">${especie}</em>
                `;
                especiesList.appendChild(li);
            });

            // Médias
            const tempMedia = (coletas.reduce((sum, c) => sum + c.temp, 0) / coletas.length).toFixed(1);
            const profMedia = (coletas.reduce((sum, c) => sum + c.prof, 0) / coletas.length).toFixed(1);
            const salMedia = (coletas.reduce((sum, c) => sum + c.sal, 0) / coletas.length).toFixed(1);

            document.getElementById('medias').innerHTML = `
                <p><strong>Temperatura:</strong> ${tempMedia}°C</p>
                <p><strong>Profundidade:</strong> ${profMedia}m</p>
                <p><strong>Salinidade:</strong> ${salMedia} PSU</p>
            `;
        }

        atualizarEstatisticas();
    </script>
</body>
</html>

Abra no navegador! Dashboard completo e interativo! 📊🗺️


🎓 Integrar com GeoJSON

// Carregar GeoJSON
fetch('coletas.geojson')
    .then(response => response.json())
    .then(data => {
        L.geoJSON(data, {
            onEachFeature: function(feature, layer) {
                const props = feature.properties;
                layer.bindPopup(`
                    <h3>${props.nome}</h3>
                    <p><strong>Espécie:</strong> ${props.especie}</p>
                `);
            }
        }).addTo(map);
    });

🎓 Checklist desta Lição

  • [ ] Criei mapa básico com Leaflet
  • [ ] Adicionei marcadores interativos
  • [ ] Customizei popups com HTML
  • [ ] Implementei controle de camadas
  • [ ] Desenvolvi dashboard completo

Se marcou tudo, você completou Visualização Web! 🎉


➡️ Próximos Passos

Parabéns! Você domina desenvolvimento web para visualização de dados! 🌐

Próximo módulo: - 4-Casos-Praticos (Projetos completos de Oceanografia)


📝 Resumo de Funções Leaflet

Função Uso
L.map() Criar mapa
L.tileLayer() Adicionar camada base
L.marker() Adicionar marcador
L.circleMarker() Círculo no mapa
L.polygon() Polígono
L.layerGroup() Agrupar camadas
L.control.layers() Controle de camadas

Você é um desenvolvedor web completo! 🌐✨

Pronto para criar dashboards profissionais para pesquisa! 🚀

🌐 Git, GitHub e GitHub Pages

🎯 Objetivo

Aprender a versionar seu projeto com Git, hospedar no GitHub e publicar páginas estáticas (mapas/dashboards) com GitHub Pages.


🛠️ Instalação e Configuração (Windows)

  1. Instale Git: https://git-scm.com/download/win
  2. Abra "Git Bash" ou PowerShell
  3. Configure sua identidade:
git config --global user.name "Seu Nome"
git config --global user.email "seu@email"

— Opcional: instalar GitHub CLI: https://cli.github.com/


📦 Iniciar Repositório Local

No diretório do projeto (esta pasta):

git init
git branch -M main
git add .
git commit -m "Inicial: tutorial LAFIC (módulos 0-6, exemplos)"

— Cria .git e registra estado inicial.


☁️ Criar Repositório no GitHub

Pelo navegador: - Vá a https://github.com/new - Nome: tutorial-LAFIC (exemplo) - Público (para GitHub Pages) - Crie sem README (já temos)

Depois, vincule remoto e envie:

git remote add origin https://github.com/<seu-usuario>/<seu-repo>.git
git push -u origin main

— Se pedir login/token, gere um PAT: https://github.com/settings/tokens


🗺️ Publicar com GitHub Pages (site estático)

GitHub Pages hospeda HTML/CSS/JS (ex.: mapas Leaflet, dashboards front-end).

  1. No repositório no GitHub, acesse Settings → Pages
  2. Build and deployment:
  3. Source: Deploy from a branch
  4. Branch: main
  5. Folder: /root (ou /docs)
  6. Salvar → espere 1–2 minutos
  7. Seu site: https://<usuario>.github.io/<repo>/

Publicar página index.html

Crie uma pasta docs/ (ou use raiz) com seu index.html (ex.: dashboard front-end):

mkdir docs
copy frontend\index.html docs\index.html
copy frontend\style.css docs\style.css
copy frontend\script.js docs\script.js

git add docs
git commit -m "Publicar dashboard estático em GitHub Pages"
git push

— GH Pages servirá docs/index.html.

Publicar mapas gerados (Folium)

Arquivos .html gerados (ex.: distribuicao_espacial.html) devem ser copiados para docs/:

copy 4-Casos-Praticos\distribuicao_espacial.html docs\distribuicao_espacial.html

git add docs\distribuicao_espacial.html
git commit -m "Publicar mapa Folium"
git push

Acesse: https://<usuario>.github.io/<repo>/distribuicao_espacial.html


🔒 Dicas de Segurança

  • Nunca commitar senhas/tokens
  • Adicionar .gitignore para venv/, __pycache__/, etc.
echo __pycache__/> .gitignore
echo venv/> .gitignore
echo .ipynb_checkpoints/> .gitignore
echo *.pyc>> .gitignore

— Commit: git add .gitignore && git commit -m "Add .gitignore" && git push


🔄 Fluxo de Trabalho Sugerido

# 1. Edite/crie arquivos
# 2. Veja mudanças
git status

# 3. Selecione para commit
git add caminho/do/arquivo

# 4. Commit com mensagem clara
git commit -m "Adicionar lição de regressão (módulo 5)"

# 5. Envie ao GitHub
git push

— Para colaborações: use branches (git checkout -b feature/nome), PRs e reviews.


🧪 Verificação Rápida

Depois do push, confira: - Repositório mostra seus commits - GH Pages ativo (Settings → Pages) - Site acessível na URL

— Problemas comuns: branch errado, pasta Pages não configurada, arquivos faltando.


🎓 Checklist

  • [ ] Repositório Git inicializado
  • [ ] Remote GitHub configurado
  • [ ] Commit e push funcionando
  • [ ] GH Pages habilitado
  • [ ] Dashboard/Mapas publicados

Com isso, você publica seus resultados científicos online de forma profissional! 🚀