Информер погоды на сайте — api OpenWeatherMap

JavaScript
65044 просмотра

Виджет погоды на сайте — это почти ритуал посвящения в мир API. Вы берёте чужие данные, делаете один запрос, получаете JSON — и вдруг на вашей странице появляется живая температура. Магия. В этой статье разберём, как подключить погоду через OpenWeatherMap API: сервис бесплатный, стабильный и отлично подходит для практики. И главное — делать это будем через чистый JavaScript, без всяких серверов — и в итоге получим готовый информер погоды на сайт.

Виджет погоды на сайте через OpenWeatherMap API — пример

Из всех доступных погода API для разработчиков OpenWeatherMap выделяется щедрым бесплатным тарифом: до 60 запросов в минуту и до 1 000 000 запросов в месяц. Для информера на обычном сайте или блоге этого хватит с огромным запасом — разве что ваши посетители не обновляют страницу раз в секунду. Поддерживается CORS, то есть запрос можно делать прямо из браузера.

Шаг 1 — Получаем OpenWeatherMap API key

Чтобы получить OpenWeatherMap API key, идём на openweathermap.org и регистрируемся: email, пароль, подтверждение. Ничего необычного.

Регистрация на OpenWeatherMap — шаг создания аккаунта

После входа в личный кабинет переходим на вкладку My API keys — там уже будет готовый ключ по умолчанию. Копируем и держим под рукой.

Вкладка API keys в личном кабинете OpenWeatherMap
Новый ключ активируется не мгновенно — может потребоваться от нескольких минут до нескольких часов. Если сразу получаете ошибку 401 — просто подождите. Это нормально, не баг.

Шаг 2 — Разбираемся в ответе API

Прежде чем писать код, посмотрим что именно возвращает сервис. Самый простой запрос — погода по названию города:

# GET-запрос для получения текущей погоды по названию города
https://api.openweathermap.org/data/2.5/weather?q=Moscow&units=metric&lang=ru&appid=ВАШ_КЛЮЧ

Параметры запроса:

  • q=Moscow — название города (английское или транслит)
  • units=metric — температура в градусах Цельсия. Без этого параметра вернётся Кельвин — и вы будете думать, что в Москве 286 градусов жары
  • lang=ru — описание погоды на русском
  • appid=... — ваш API ключ

В ответ приходит JSON. Вот его самые нужные поля:

{
  "name": "Moscow",           // название города
  "sys": { "country": "RU" },// код страны
  "main": {
    "temp": 12.4,             // температура в °C (при units=metric)
    "feels_like": 10.8,       // ощущаемая
    "humidity": 72,           // влажность, %
    "pressure": 1013          // давление, гПа
  },
  "weather": [{
    "description": "облачно", // текстовое описание (на русском при lang=ru)
    "icon": "04d"             // код иконки для отображения
  }],
  "wind": {
    "speed": 4.2              // скорость ветра, м/с
  }
}

Иконки погоды — это приятный бонус: OpenWeatherMap отдаёт готовые PNG по предсказуемому URL. Берём код из поля icon и подставляем:

# URL иконки: подставьте код из поля icon в ответе API
https://openweathermap.org/img/wn/04d@2x.png

Способ 1 — Погода через чистый JavaScript

OpenWeatherMap API поддерживает CORS — это значит, что запрос можно делать прямо из браузера, никакой сервер не нужен. Несколько строк JS — и готово.

При таком подходе API ключ виден в исходном коде страницы. Для личного сайта или учебного проекта это вполне приемлемо: бесплатный тариф всё равно ограничен лимитами. Если нужна дополнительная безопасность — смотрите Способ 3 ниже.

HTML-разметка виджета:

<div class="weather-widget" id="weather">
    <div class="weather-widget__city">—</div>
    <div class="weather-widget__temp">—</div>
    <img class="weather-widget__icon" src="" alt="" />
    <div class="weather-widget__desc">—</div>
    <div class="weather-widget__meta">
        <span class="weather-widget__wind">Ветер: —</span>
        <span class="weather-widget__humidity">Влажность: —</span>
    </div>
</div>

JavaScript:

const API_KEY = 'ВАШ_КЛЮЧ';
const CITY    = 'Moscow';
const URL     = `https://api.openweathermap.org/data/2.5/weather`
              + `?q=${CITY}&units=metric&lang=ru&appid=${API_KEY}`;

fetch(URL)
    .then(res => res.json())
    .then(data => {
        const w = document.getElementById('weather');

        w.querySelector('.weather-widget__city').textContent =
            `${data.name}, ${data.sys.country}`;

        w.querySelector('.weather-widget__temp').textContent =
            `${Math.round(data.main.temp)}°C`;

        const icon = w.querySelector('.weather-widget__icon');
        icon.src = `https://openweathermap.org/img/wn/${data.weather[0].icon}@2x.png`;
        icon.alt = data.weather[0].description;

        w.querySelector('.weather-widget__desc').textContent =
            data.weather[0].description;

        w.querySelector('.weather-widget__wind').textContent =
            `Ветер: ${data.wind.speed} м/с`;

        w.querySelector('.weather-widget__humidity').textContent =
            `Влажность: ${data.main.humidity}%`;
    })
    .catch(() => {
        document.getElementById('weather').textContent =
            'Не удалось загрузить данные о погоде';
    });

На что обратить внимание:

  • units=metric уже возвращает Цельсии — ничего вычитать не нужно. Температура 12.4 означает 12.4 °C
  • Math.round() убирает лишнее: API возвращает значения вроде 12.37, а нам нужно просто «12»
  • .catch() обязателен — без него пользователь увидит пустой виджет и не поймёт что пошло не так

Способ 2 — Геолокация: город определяется автоматически

Зачем прописывать город вручную, если браузер умеет определять местоположение? navigator.geolocation — встроенный инструмент, никаких библиотек. Пользователь нажимает «Разрешить» — и видит погоду именно там, где он находится.

const API_KEY = 'ВАШ_КЛЮЧ';

function showWeather(lat, lon) {
    const URL = `https://api.openweathermap.org/data/2.5/weather`
              + `?lat=${lat}&lon=${lon}&units=metric&lang=ru&appid=${API_KEY}`;

    fetch(URL)
        .then(res => res.json())
        .then(data => {
            const w = document.getElementById('weather');

            w.querySelector('.weather-widget__city').textContent =
                `${data.name}, ${data.sys.country}`;

            w.querySelector('.weather-widget__temp').textContent =
                `${Math.round(data.main.temp)}°C`;

            const icon = w.querySelector('.weather-widget__icon');
            icon.src = `https://openweathermap.org/img/wn/${data.weather[0].icon}@2x.png`;
            icon.alt = data.weather[0].description;

            w.querySelector('.weather-widget__desc').textContent =
                data.weather[0].description;

            w.querySelector('.weather-widget__wind').textContent =
                `Ветер: ${data.wind.speed} м/с`;

            w.querySelector('.weather-widget__humidity').textContent =
                `Влажность: ${data.main.humidity}%`;
        })
        .catch(() => {
            document.getElementById('weather').textContent =
                'Не удалось загрузить данные';
        });
}

if ('geolocation' in navigator) {
    navigator.geolocation.getCurrentPosition(
        pos => showWeather(pos.coords.latitude, pos.coords.longitude),
        ()  => showWeather(55.75, 37.62) // Москва как запасной вариант
    );
}

Если пользователь отклонил запрос геолокации — срабатывает второй аргумент getCurrentPosition . В примере выше мы в этом случае показываем погоду Москвы по координатам — это лучше, чем пустой виджет. Можно также показать форму ввода города вручную.

Геолокация работает только на HTTPS. На обычном HTTP браузер её заблокирует. При тестировании локально используйте localhost — он является исключением и работает без сертификата.

Способ 3 — PHP как прокси: ключ остаётся на сервере

Если вам важно скрыть API ключ от посторонних — делаем тонкий серверный прокси. JavaScript запрашивает не OpenWeatherMap напрямую, а ваш PHP скрипт, который уже сам идёт к API. Ключ хранится только на сервере.

Файл weather.php :

<?php
header('Content-Type: application/json; charset=utf-8');

$apiKey = 'ВАШ_КЛЮЧ'; // хранится только здесь, снаружи не виден
$city   = htmlspecialchars($_GET['city'] ?? 'Moscow', ENT_QUOTES);

$url      = "https://api.openweathermap.org/data/2.5/weather"
          . "?q={$city}&units=metric&lang=ru&appid={$apiKey}";
$response = file_get_contents($url);

echo $response !== false ? $response : json_encode(['error' => 'API unavailable']);

JavaScript теперь обращается к вашему скрипту — структура ответа та же:

fetch('/weather.php?city=Moscow')
    .then(res => res.json())
    .then(data => {
        document.querySelector('.weather-widget__city').textContent =
            `${data.name}, ${data.sys.country}`;
        document.querySelector('.weather-widget__temp').textContent =
            `${Math.round(data.main.temp)}°C`;
        // ... остальные поля — как в Способе 1
    });
Если нужно кешировать ответ — добавьте в PHP запись в файл или базу данных и проверку времени последнего обновления. Погода редко меняется быстрее, чем раз в 10 минут, а API запросы при этом можно сократить в разы.

Пример виджета

Живой пример — виджет запрашивает геолокацию и показывает погоду в вашем городе. Если вы отклоните запрос или геолокация недоступна — покажет Москву:

Итого: как добавить погоду на сайт

  • Только JavaScript — самый простой вариант. Один файл, никакого сервера. API ключ виден в коде, но для личного проекта это приемлемо.
  • JavaScript + Geolocation — определяем город автоматически. Пользователь видит свою погоду без ввода чего-либо, а ваш виджет выглядит умнее.
  • PHP + JavaScript — если нужна безопасность ключа или серверное кеширование. Сложнее на шаг, но ключ снаружи не виден.

Главное, что стоит запомнить: при units=metric температура приходит уже в Цельсиях — конвертировать ничего не нужно. И не забывайте .catch() — API иногда недоступен, и пользователь не должен видеть сломанный виджет.

Вам может быть интересно:
Swiper.js — слайдер для сайта: настройки и примеры
Swiper.js — как подключить и настроить слайдер на сайте
Что такое функция в программировании — типы и примеры на JavaScript и Python
Что такое функция в программировании?
Promise в JavaScript — промисы JS простыми словами для начинающих
Promise в JavaScript простыми словами — полное руководство
Анимация частиц и GLSL-шейдеры в PixiJS 8 — живой пример в браузере
Изучаем PixiJS. Часть 2 — продвинутая анимация и GLSL-шейдеры
Комментарии 0 Разные мнения приветствуются. Здесь можно спорить и обсуждать, но уважительно и без токсичности.
Отмена