Linha do tempo 24h de temperatura

24-Hour Temperature Timeline with rain probability chart

Neste tutorial vamos usar os primeiros 8 itens do endpoint /forecast (24 horas, cada um com 3h de intervalo) para construir um grafico de linha de temperatura e barras de probabilidade de chuva. SVG puro, sem bibliotecas.

In this tutorial we'll use the first 8 items from the /forecast endpoint (24 hours, each 3h apart) to build a temperature line chart and rain probability bars. Pure SVG, no libraries.

1. Extrair dados das proximas 24h / Extract next 24h data

O endpoint /forecast retorna uma lista de previsoes a cada 3 horas. Os primeiros 8 itens cobrem as proximas 24 horas.

The /forecast endpoint returns a list of forecasts every 3 hours. The first 8 items cover the next 24 hours.

const API_KEY = 'YOUR_API_KEY';
const BASE = 'https://weather.api.insyde.one';

async function fetchForecast(city) {
  const qs = new URLSearchParams({ q: city, units: 'metric', key: API_KEY });
  const res = await fetch(`${BASE}/forecast?${qs}`);
  return res.json();
}

const data = await fetchForecast('São Paulo,BR');

// First 8 items = next 24 hours (3h intervals)
const next24h = data.list.slice(0, 8);

// Extract temperature and rain probability
const points = next24h.map(item => ({
  time: item.dt_txt.slice(11, 16),     // "06:00"
  temp: Math.round(item.main.temp),    // 22
  pop:  Math.round(item.pop * 100)     // 10 (percentage)
}));

2. Construir SVG / Build SVG

Para desenhar a linha de temperatura, mapeamos os valores de temp para coordenadas Y dentro de um viewBox SVG. Usamos <polyline> para conectar os pontos e um <linearGradient> para a area preenchida abaixo da linha.

To draw the temperature line, we map temp values to Y coordinates within an SVG viewBox. We use <polyline> to connect the points and a <linearGradient> for the filled area below the line.

const svgW = 700, svgH = 200;
const padL = 40, padR = 20, padT = 30, padB = 30;
const chartW = svgW - padL - padR;
const chartH = svgH - padT - padB;

// Find temp range for Y scaling
const temps = points.map(p => p.temp);
const minT = Math.floor(Math.min(...temps) / 4) * 4;
const maxT = Math.ceil(Math.max(...temps) / 4) * 4;

// Map data to SVG coordinates
function toX(i) { return padL + (i / 7) * chartW; }
function toY(temp) {
  return padT + (1 - (temp - minT) / (maxT - minT)) * chartH;
}

// Build polyline points string
const linePoints = points
  .map((p, i) => `${toX(i)},${toY(p.temp)}`)
  .join(' ');

// Build filled area polygon (line + bottom corners)
const areaPoints = linePoints
  + ` ${toX(7)},${padT + chartH} ${toX(0)},${padT + chartH}`;

3. Barras de chuva / Rain bars

Abaixo do grafico SVG de temperatura, adicionamos barras horizontais para a probabilidade de chuva (pop). A altura e proporcional a porcentagem, e a opacidade do azul indica a intensidade.

Below the SVG temperature chart, we add bars for rain probability (pop). The height is proportional to the percentage, and the blue opacity indicates intensity.

function buildRainBars(points) {
  const maxH = 60; // max bar height in px

  return points.map(p => {
    const h = (p.pop / 100) * maxH;
    const opacity = 0.3 + (p.pop / 100) * 0.7;

    return `<div class="rain-col">
      <span class="rain-pct">${p.pop}%</span>
      <div class="rain-bar" style="
        height: ${h}px;
        background: rgba(59,130,246,${opacity});
      "></div>
      <span class="rain-time">${p.time}</span>
    </div>`;
  }).join('');
}
Nota / Note: Each forecast item is 3 hours apart. 8 items = 24 hours. Cada item de previsao tem 3 horas de intervalo. 8 itens = 24 horas.

4. Exemplo completo / Complete example

Juntando tudo: buscamos a previsao, extraimos os 8 primeiros itens, desenhamos a polyline SVG para temperatura e as barras de chuva abaixo.

Putting it all together: fetch the forecast, extract the first 8 items, draw the SVG polyline for temperature and the rain bars below.

async function renderTimeline(city) {
  const data = await fetchForecast(city);
  const next24h = data.list.slice(0, 8);

  const points = next24h.map(item => ({
    time: item.dt_txt.slice(11, 16),
    temp: Math.round(item.main.temp),
    pop:  Math.round(item.pop * 100)
  }));

  // Temperature range
  const temps = points.map(p => p.temp);
  const minT = Math.floor(Math.min(...temps) / 4) * 4;
  const maxT = Math.ceil(Math.max(...temps) / 4) * 4;

  const svgW = 700, svgH = 200;
  const padL = 40, padR = 20, padT = 30, padB = 30;
  const chartW = svgW - padL - padR;
  const chartH = svgH - padT - padB;

  function toX(i) { return padL + (i / 7) * chartW; }
  function toY(t) { return padT + (1 - (t - minT) / (maxT - minT)) * chartH; }

  const linePoints = points.map((p, i) =>
    `${toX(i)},${toY(p.temp)}`
  ).join(' ');

  const areaPoints = linePoints
    + ` ${toX(7)},${padT + chartH} ${toX(0)},${padT + chartH}`;

  // Build SVG + rain bars HTML
  const html = `...SVG and rain bars markup...`;
  document.getElementById('content').innerHTML = html;
}

renderTimeline('São Paulo,BR');

O demo acima mostra o resultado final com dados reais de Sao Paulo. A linha azul conecta os 8 pontos de temperatura e a area preenchida com gradiente reforça a variacao termica. As barras de chuva abaixo usam opacidade variavel para indicar a intensidade.

The demo above shows the final result with realistic Sao Paulo data. The blue line connects the 8 temperature points and the gradient-filled area reinforces the thermal variation. The rain bars below use variable opacity to indicate intensity.

Back to Weather API docs