Frente fria vista do espaço

Posted on: June 05, 2025 08:21 PM

Posted by: Renato

Categories: Laravel Dicas

Views: 140

Frente fria - vista do espaço

Imagens de uma frente fria vista do espaço.

A imagem representa uma formação de nuvens bastante característica, conhecida como frente fria ou linha de instabilidade, geralmente associada a sistemas meteorológicos frontais. A imagem mostra claramente uma longa faixa de nuvens se estendendo de norte a sul sobre a América do Sul, mais precisamente sobre a Argentina, com o Brasil à direita da imagem.

A formação é típica de frentes frias, onde o ar frio (à esquerda) empurra o ar quente (à direita), forçando o ar quente a subir. Esse movimento gera condensação e, consequentemente, essa faixa contínua de nuvens densas.

A formação de nuvens é linear e se alinha com a borda dos Andes, o que é comum devido à topografia que canaliza os ventos e intensifica o contraste térmico entre as massas de ar. Essa imagem é um exemplo impressionante da interação entre clima e geografia terrestre.

- Existe alguma api que posso consumir para ver previsao do tempo e como posso fazer sito com laravel?


🌤️ APIs para Previsão do Tempo

  1. OpenWeatherMap

    • Site: https://openweathermap.org/api

    • Tem plano gratuito com limites razoáveis.

    • Fornece previsão atual, por hora e por 7 dias, além de mapas climáticos.

    • Necessário registrar e obter uma API Key.

  2. WeatherAPI

  3. Climacell (Tomorrow.io)

    • Site: https://www.tomorrow.io

    • Oferece insights hiperlocais (útil para previsão em regiões específicas, como a borda dos Andes).


🚀 Exemplo de Integração no Laravel com OpenWeatherMap

1. Instale o HTTP Client (Laravel 7+ já vem com Http):

composer require guzzlehttp/guzzle

2. No .env, adicione:

OPENWEATHER_API_KEY=your_api_key_aqui

3. Crie um Controller:

php artisan make:controller WeatherController

4. Código no controller:

use Illuminate\Support\Facades\Http;

class WeatherController extends Controller
{
    public function getWeather($city = 'Buenos Aires')
    {
        $apiKey = env('OPENWEATHER_API_KEY');
        $response = Http::get("https://api.openweathermap.org/data/2.5/weather", [
            'q' => $city,
            'appid' => $apiKey,
            'units' => 'metric',
            'lang' => 'pt_br',
        ]);

        if ($response->successful()) {
            return response()->json($response->json());
        }

        return response()->json(['error' => 'Erro ao obter dados meteorológicos'], 500);
    }
}

5. Rota em web.php ou api.php:

Route::get('/weather/{city?}', [WeatherController::class, 'getWeather']);

📌 Resultado

Acesse:

http://localhost:8000/weather/São%20Paulo

E receba uma resposta como:

{
  "main": {
    "temp": 21.6,
    "humidity": 78
  },
  "weather": [
    {
      "description": "nuvens dispersas"
    }
  ]
}

Ótimo! Vamos mostrar a previsão do tempo em uma view Blade, com Laravel (pode ser usado com Livewire depois, se quiser reatividade).


✅ Etapas para exibir previsão do tempo em uma view Blade

1. 🔧 Controller: ajustar para enviar os dados para a view

Atualize seu WeatherController para:

use Illuminate\Support\Facades\Http;

class WeatherController extends Controller
{
    public function show($city = 'Buenos Aires')
    {
        $apiKey = env('OPENWEATHER_API_KEY');
        $response = Http::get("https://api.openweathermap.org/data/2.5/weather", [
            'q' => $city,
            'appid' => $apiKey,
            'units' => 'metric',
            'lang' => 'pt_br',
        ]);

        if ($response->successful()) {
            $weather = $response->json();
            return view('weather.show', compact('weather', 'city'));
        }

        return view('weather.show', ['weather' => null, 'city' => $city]);
    }
}

2. 🛣️ Rota (em web.php)

Route::get('/previsao/{city?}', [WeatherController::class, 'show']);

3. 🖼️ Criar a view Blade: resources/views/weather/show.blade.php

@extends('layouts.app')

@section('content')
<div class="max-w-md mx-auto mt-10 bg-white shadow-xl rounded-xl p-6 text-center">
    <h1 class="text-2xl font-bold mb-4">Previsão do Tempo</h1>

    <form method="GET" action="{{ url('/previsao') }}" class="mb-4">
        <input type="text" name="city" placeholder="Digite a cidade"
               value="{{ old('city', $city) }}"
               class="border px-3 py-2 rounded w-full mb-2" />
        <button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded">
            Buscar
        </button>
    </form>

    @if ($weather)
        <h2 class="text-xl font-semibold">{{ $city }}</h2>
        <p class="text-gray-700 text-lg">🌡️ {{ $weather['main']['temp'] }}°C</p>
        <p class="text-gray-500 capitalize">☁️ {{ $weather['weather'][0]['description'] }}</p>
        <p class="text-gray-500">💧 Umidade: {{ $weather['main']['humidity'] }}%</p>
    @else
        <p class="text-red-500">Não foi possível obter a previsão para "{{ $city }}"</p>
    @endif
</div>
@endsection

4. 💡 Exemplo de layout base (caso não tenha um)

Crie resources/views/layouts/app.blade.php se ainda não existir:

<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <title>Previsão do Tempo</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
</head>
<body class="bg-gray-100">
    @yield('content')
</body>
</html>

🔁 Livewire (opcional)

Perfeito! Vamos transformar a busca em reativa com Livewire, além de adicionar ícones meteorológicos, previsão por hora, e um mapa com a localização. Aqui está o passo a passo:


✅ Etapas completas com Livewire + ícones + previsão por hora + mapa


1. 📦 Instale o Livewire (caso ainda não tenha)

composer require livewire/livewire
php artisan livewire:publish

2. 🧠 Crie o componente Livewire

php artisan make:livewire WeatherForecast

3. ✍️ Código do componente app/Livewire/WeatherForecast.php

namespace App\Livewire;

use Livewire\Component;
use Illuminate\Support\Facades\Http;

class WeatherForecast extends Component
{
    public $city = 'Buenos Aires';
    public $weather;
    public $hourly;

    public function mount()
    {
        $this->fetchWeather();
    }

    public function updatedCity()
    {
        $this->fetchWeather();
    }

    public function fetchWeather()
    {
        $apiKey = env('OPENWEATHER_API_KEY');

        // Get coordinates first
        $geo = Http::get('http://api.openweathermap.org/geo/1.0/direct', [
            'q' => $this->city,
            'limit' => 1,
            'appid' => $apiKey,
        ])->json();

        if (empty($geo)) {
            $this->weather = null;
            $this->hourly = [];
            return;
        }

        $lat = $geo[0]['lat'];
        $lon = $geo[0]['lon'];

        $response = Http::get("https://api.openweathermap.org/data/2.5/onecall", [
            'lat' => $lat,
            'lon' => $lon,
            'exclude' => 'minutely,daily,alerts',
            'units' => 'metric',
            'appid' => $apiKey,
            'lang' => 'pt_br',
        ]);

        if ($response->successful()) {
            $data = $response->json();
            $this->weather = $data['current'];
            $this->hourly = array_slice($data['hourly'], 0, 6); // próximas 6 horas
        } else {
            $this->weather = null;
            $this->hourly = [];
        }
    }

    public function render()
    {
        return view('livewire.weather-forecast');
    }
}

4. 🖼️ View do componente: resources/views/livewire/weather-forecast.blade.php

<div class="max-w-xl mx-auto mt-10 p-6 bg-white rounded-lg shadow-md text-center">
    <h1 class="text-2xl font-bold mb-4">Previsão do Tempo</h1>

    <input type="text" wire:model.debounce.1000ms="city"
           placeholder="Digite a cidade"
           class="border px-4 py-2 rounded w-full mb-4" />

    @if ($weather)
        <h2 class="text-xl font-semibold">{{ $city }}</h2>
        <div class="flex flex-col items-center">
            <img src="https://openweathermap.org/img/wn/{{ $weather['weather'][0]['icon'] }}@2x.png" alt="icone clima">
            <p class="text-lg font-bold">🌡️ {{ round($weather['temp']) }}°C</p>
            <p class="capitalize text-gray-600">☁️ {{ $weather['weather'][0]['description'] }}</p>
            <p class="text-sm text-gray-500">💧 Umidade: {{ $weather['humidity'] }}%</p>
        </div>

        <h3 class="mt-6 text-lg font-bold">Próximas horas</h3>
        <div class="grid grid-cols-3 gap-4 mt-3 text-sm">
            @foreach ($hourly as $hour)
                <div class="bg-gray-100 rounded p-2">
                    <p>{{ \Carbon\Carbon::createFromTimestamp($hour['dt'])->format('H:i') }}</p>
                    <img src="https://openweathermap.org/img/wn/{{ $hour['weather'][0]['icon'] }}.png" class="mx-auto">
                    <p>{{ round($hour['temp']) }}°C</p>
                </div>
            @endforeach
        </div>

        <h3 class="mt-6 text-lg font-bold">📍 Mapa</h3>
        <iframe
            width="100%"
            height="250"
            class="rounded mt-2"
            frameborder="0"
            scrolling="no"
            marginheight="0"
            marginwidth="0"
            src="https://maps.google.com/maps?q={{ urlencode($city) }}&t=&z=10&ie=UTF8&iwloc=&output=embed">
        </iframe>
    @else
        <p class="text-red-500">Não foi possível obter a previsão para "{{ $city }}"</p>
    @endif
</div>

5. 🛣️ Use o componente em uma página Blade

Crie resources/views/weather.blade.php:

@extends('layouts.app')

@section('content')
    @livewire('weather-forecast')
@endsection

6. 📄 Adicione a rota

Em routes/web.php:

Route::get('/clima', function () {
    return view('weather');
});

7. 🧩 Inclua Livewire no layout base (layouts/app.blade.php)

No <head>:

@livewireStyles

Antes de fechar </body>:

@livewireScripts

✅ Pronto! Agora:

  • A previsão do tempo é atualizada reativamente ao digitar a cidade.

  • Mostra ícone do clima atual, previsão para 6 horas e mapa da cidade.

  • Pode ser expandido para incluir previsão diária, radar, alertas, etc.


Ótimo! Vamos criar uma versão mais avançada e estilizada do componente com:


✅ Recursos adicionais:

  • Previsão para os próximos 5 dias

  • Livewire reativo (sem recarregar a página)

  • Ícones de clima

  • Gráfico simples (temperatura máxima/mínima por dia)

  • Estilo com Tailwind CSS

  • Mapa da cidade


🧠 Atualização do componente Livewire

app/Livewire/WeatherForecast.php

Atualize o componente para buscar também a previsão diária:

namespace App\Livewire;

use Livewire\Component;
use Illuminate\Support\Facades\Http;

class WeatherForecast extends Component
{
    public $city = 'São Paulo';
    public $weather;
    public $daily = [];

    public function mount()
    {
        $this->fetchWeather();
    }

    public function updatedCity()
    {
        $this->fetchWeather();
    }

    public function fetchWeather()
    {
        $apiKey = env('OPENWEATHER_API_KEY');

        $geo = Http::get('http://api.openweathermap.org/geo/1.0/direct', [
            'q' => $this->city,
            'limit' => 1,
            'appid' => $apiKey,
        ])->json();

        if (empty($geo)) {
            $this->weather = null;
            $this->daily = [];
            return;
        }

        $lat = $geo[0]['lat'];
        $lon = $geo[0]['lon'];

        $response = Http::get("https://api.openweathermap.org/data/2.5/onecall", [
            'lat' => $lat,
            'lon' => $lon,
            'exclude' => 'minutely,hourly,alerts',
            'units' => 'metric',
            'appid' => $apiKey,
            'lang' => 'pt_br',
        ]);

        if ($response->successful()) {
            $data = $response->json();
            $this->weather = $data['current'];
            $this->daily = array_slice($data['daily'], 0, 5);
        } else {
            $this->weather = null;
            $this->daily = [];
        }
    }

    public function render()
    {
        return view('livewire.weather-forecast');
    }
}

🖼️ View com Estilo + Gráfico

resources/views/livewire/weather-forecast.blade.php

<div class="max-w-3xl mx-auto mt-10 p-6 bg-white shadow-lg rounded-xl">
    <h1 class="text-3xl font-bold text-center mb-6">🌤️ Previsão do Tempo</h1>

    <input type="text" wire:model.debounce.1000ms="city"
           placeholder="Digite a cidade"
           class="border border-gray-300 px-4 py-2 rounded w-full mb-4 shadow-sm focus:ring focus:ring-blue-200" />

    @if ($weather)
        <div class="text-center">
            <h2 class="text-2xl font-semibold">{{ $city }}</h2>
            <img src="https://openweathermap.org/img/wn/{{ $weather['weather'][0]['icon'] }}@2x.png" class="mx-auto">
            <p class="text-lg font-bold">🌡️ {{ round($weather['temp']) }}°C</p>
            <p class="capitalize text-gray-600">☁️ {{ $weather['weather'][0]['description'] }}</p>
            <p class="text-sm text-gray-500">💧 Umidade: {{ $weather['humidity'] }}%</p>
        </div>

        <div class="mt-6">
            <h3 class="text-xl font-bold mb-2">🗓️ Previsão para os próximos 5 dias</h3>
            <div class="grid grid-cols-1 md:grid-cols-5 gap-4 text-center">
                @foreach ($daily as $day)
                    <div class="bg-blue-50 rounded-lg p-3 shadow-sm">
                        <p class="font-medium">{{ \Carbon\Carbon::createFromTimestamp($day['dt'])->translatedFormat('D d/M') }}</p>
                        <img src="https://openweathermap.org/img/wn/{{ $day['weather'][0]['icon'] }}.png" class="mx-auto">
                        <p class="text-sm capitalize">{{ $day['weather'][0]['description'] }}</p>
                        <p class="text-sm">🌡️ Máx: {{ round($day['temp']['max']) }}°C</p>
                        <p class="text-sm">🌡️ Mín: {{ round($day['temp']['min']) }}°C</p>
                    </div>
                @endforeach
            </div>
        </div>

        <div class="mt-8">
            <h3 class="text-xl font-bold mb-2">📍 Localização</h3>
            <iframe
                width="100%"
                height="250"
                class="rounded-lg shadow"
                frameborder="0"
                scrolling="no"
                marginheight="0"
                marginwidth="0"
                src="https://maps.google.com/maps?q={{ urlencode($city) }}&t=&z=10&ie=UTF8&iwloc=&output=embed">
            </iframe>
        </div>
    @elseif(strlen($city) > 2)
        <p class="text-red-500 text-center">❌ Não foi possível encontrar "{{ $city }}"</p>
    @endif
</div>

🎯 Resultado:

  • ⚡ Reativo: digite o nome da cidade → tudo se atualiza automaticamente

  • 📅 Previsão diária (5 dias)

  • 🌐 Mapa do Google Maps

  • ☁️ Ícones climáticos + descrições

  • 🎨 Layout bonito com Tailwind


Perfeito! Vamos adicionar agora um gráfico interativo de temperatura (máx e mín) para os próximos 5 dias usando Chart.js, integrado com Livewire.


🎯 Objetivo

  • Mostrar a temperatura máxima e mínima por dia em um gráfico de linha usando Chart.js

  • O gráfico será atualizado automaticamente ao trocar a cidade


🧩 Passos

1. 📦 Adicione Chart.js

No seu Blade principal (ex: resources/views/layouts/app.blade.php ou diretamente no componente), inclua:

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

2. 🧠 Atualize o componente Blade

resources/views/livewire/weather-forecast.blade.php (adicione isso após a previsão de 5 dias)

<div class="mt-10">
    <h3 class="text-xl font-bold mb-2">📊 Gráfico de Temperaturas</h3>
    <canvas id="tempChart" height="150"></canvas>
</div>

@push('scripts')
<script>
    document.addEventListener('livewire:load', () => {
        let chart;

        Livewire.hook('message.processed', (message, component) => {
            const daily = @json($daily);

            const labels = daily.map(d => {
                const date = new Date(d.dt * 1000);
                return date.toLocaleDateString('pt-BR', { weekday: 'short', day: 'numeric' });
            });

            const maxTemps = daily.map(d => d.temp.max);
            const minTemps = daily.map(d => d.temp.min);

            const data = {
                labels: labels,
                datasets: [
                    {
                        label: 'Máxima °C',
                        data: maxTemps,
                        borderColor: 'rgb(255, 99, 132)',
                        fill: false,
                        tension: 0.2
                    },
                    {
                        label: 'Mínima °C',
                        data: minTemps,
                        borderColor: 'rgb(54, 162, 235)',
                        fill: false,
                        tension: 0.2
                    }
                ]
            };

            const config = {
                type: 'line',
                data: data,
                options: {
                    responsive: true,
                    plugins: {
                        legend: {
                            position: 'top'
                        },
                        title: {
                            display: false
                        }
                    }
                },
            };

            // destrói gráfico antigo se houver
            if (chart) chart.destroy();

            const ctx = document.getElementById('tempChart').getContext('2d');
            chart = new Chart(ctx, config);
        });
    });
</script>
@endpush

Resultado 🎉

Você verá:

  • ✅ Previsão detalhada em cards

  • ✅ Google Maps embutido

  • ✅ Gráfico de temperatura com linhas suaves e cores distintas

  • ✅ Atualização automática via Livewire


Fim e boa sorte!


2

Share

Donate to Site


About Author

Renato

Developer

Add a Comment

Blog Search


Categories

Laravel (227) PHP (151) linux (124) Variados (110) ubuntu (58) Dicas (58) developer (48) postgresql (45) database (44) sql (42) Docker (32) front-end (31) mysql (31) devops (26) webdev (24) programming (23) tecnologia (19) eloquent (19) aws (19) dba (18) OUTROS (17) backend (16) laravelphp (16) debian (12) dev (12) 100DaysOfCode (10) git (10) react (10) reactjs (10) inteligencia-artificial (9) PHP Swoole (9) node (9) javascript (9) nginx (9) Architecture (8) linux-tools (8) vue (7) github (7) ciencia (7) webservice (6) jwt (6) vim (6) windows (6) arquitetura (6) nodejs (6) api (6) vscode (6) reactnative (5) rest (5) DevSecOps (5) servers (5) apache (5) macox (5) s3 (5) authentication (5) ia (5) shell (4) mongodb (4) angular (4) autenticacao (4) wsl (4) Swoole (4) lets-encrypt (4) query (4) Raspberry (4) angularjs (4) inteligenciadedados (4) Padrao de design (4) artigo (4) google (4) npm (4) openai (4) Kubernetes (4) gitlab (4) opensource (4) mariadb (4) jenkins (4) json (3) authorization (3) phpswoole (3) ddd (3) blade (3) terminal (3) log (3) mac (3) fedora (3) containers (3) ssh (3) bash (3) hardware (3) tests (3) macos (3) web (2) jobs (3) websocket (3) db (3) politica (3) js (3) mysqli (3) Black Hat (3) RabbitMQ (3) educacao (3) intel (3) CMS (2) sail (3) script (3) performance (3) bancodedados (2) tailwind (2) homeOffice (2) html (2) openswoole (2) artificialintelligence (2) security (2) seguranca (2) auth (2) cron (2) phpunit (2) kube (2) multiple_authen (2) policia (2) neovim (2) golang (2) noticias (2) livros (2) Transcribe (2) ElonMusk (2) redis (2) claude (2) ArchLinux (2) java (2) saude (1) phpfpm (2) autorizacao (2) monitoring (2) laptop (2) gnome (2) powerbi (2) telefonia (2) nvm (2) imagick (2) maps (2) colors (2) Passport (2) JQuery (2) Curisidades (2) Solid (2) zsh (2) Go (2) BigLinux (2) POO (2) LazyVim (2) gource (2) Python (2) Oauth2 (2) android (2) unix (2) magento (2) iot (2) ffmpeg (2) combustivel (2) webhook (2) microservices (2) Migration (1) workflow (1) cqrs (1) kitematic (1) geospacial (1) yeshua (1) data (1) sonarqube (1) Axios (1) pipelines (1) Mozilla (1) kvm (1) GitOps (1) sqlite (1) podcast (1) n8n (1) LaravelFilament (1) God (1) DesenvolvimentoProfissional (1) sw (1) bigtech (1) postgres (1) NoCookies (1) LeetCode (1) governancadedados (1) prf (1) nosql (1) Lideranca (1) Hackers (1) Bots (1) pytorch (1) nuxt (1) liquid (1) ec2 (1) transaction (1) c4 (1) rancher (1) algoritimo (1) Observability (1) Elasticsearch (1) translate (1) certbot (1) Oh My Zsh (1) ibm (1) escopos (1) usb (1) ckeditor (1) API_KEY_GOOGLE_MAPS (1) Manjaro (1) vicuna (1) coding (1) rust (1) markdown (1) JasperReports (1) Fibonacci (1) community (1) Samurai (1) payment (1) messaging (1) Jesus (1) flutter (1) militar (1) fullsta (1) smartphones (1) automacao (1) Monitor (1) zend (1) spaceship (1) PKCE (1) l2tp (1) Glacier (1) laraveloctane (1) Deus (1) binaural (1) gpt (1) bolsonaro (1) privacidade (1) linkedin (1) documentation (1) brain (1) adb (1) nvidia (1) host (1) ecommerce (1) c4-models (1) altadisponibilidade (1) octane (1) lucena (1) http (1) TypeScript (1) chatgpt (1) idiomas (1) eventdrive (1) uuid (1) restfull (1) aplicativo (1) optimization (1) mapas (1) Fetch (1) collections (1) RustLang (1) matematica (1) Filament (1) compactar (1) paypal (1) microg (1) forcas armadas (1) front (1) cor (1) auth (1) modelagemdedados (1) k8s (1) gasolina (1) wsl2 (1) csv (1) soap (1) piada (1) KubeCon (1) zorin-os (1) spring-boot (1) backup (1) playwright (1) Deepin (1) storage (1) benchmark (1) networking (1) Swoole (1) biologia (1) node-red (1) LETSENCRYPT (1) Grunt (1) Diagramas (1) boot (1) haru (1) dracula (1) TrabalhoEmEquipe (1) Brasil (1) queue (1) agi (1) llama (1) hotfix (1) economia (1) transcription (1) cache (1) Amazon (1) October (1) lumen (1) Hyperf (1) replication (1) faceapp (1) vala (1) cloudstack (1) rpi (1) apple (1) oracle (1) iode (1) ffaa (1) vpn (1) MeioAmbiente (1) firefox (1) composer (1) scheduling (1) Asahi (1) pendrive (1) microservice (1) front (1) wine (1) covid19 (0) services (1) phpjasper (1) models (1) kali-linux (1) geojson (1) yarn (1) picpay (1) Monolith (1) banco (1) PNPM (1) Desenvolvedor (1) Structurizr (1) symfony (1) presenter (1) lider (1) guard (1) tensorflow (1) bootstrap (1) nuance (1) historia (1) dropbox (1) traefik (1) bug (1) akitando (1) llm (1) htm (1) transformers (1) cavalotroia (1) odd (1) m1 (1) Error (1) cinnamon (1) repmgr (1) federal (1) ruby (1) AppSec (1) orm (1) ArquiteturaDeSoftware (1) Passwordless (1) memcached (1) flow (1) compression (1) athena (1) controllers (0) OOD (0)

New Articles



Get Latest Updates by Email