週間天気予報をGitHubPagesで表示してみた


## 概要

- Open-MeteoのAPIで得られるjsonを、GitHubPagesで表示してみました。
- スマートフォン向けの都道府県庁所在地の週間天気予報アプリです。

## デモ

https://kubo-4ka.github.io/weekly-forecast/

## ソース

https://github.com/kubo-4ka/weekly-forecast/

## 主な機能
- 特徴
  - 日本全国47都道府県の天気に対応（庁所在地ベース）。
  - UTF-8絵文字で天気を視覚表現。
  - 都道府県をプルダウンから簡単に選択できます。
  - Open-MeteoというAPIから最新の天気情報を取得し、信頼できる予報を提供します。
  - 見やすいダークテーマデザインを採用し、夜間や暗い環境でも快適に利用できます。
  - スマホの縦画面表示に特化しており、最小限の操作で天気を確認できます。
  - 「予報取得」ボタンは3秒間のインターバルを設けており、APIへの負担を軽減します。

- 使い方
  - プルダウンから、見たい都道府県を選択します。
  - 「予報取得」ボタンを押し、選択した場所の最新の天気予報を取得します。

- 技術仕様
  - HTML / CSS / JavaScript（Vanilla JS）を用いたフロントエンドのみの構成
  - GitHub Pagesでホスト

## 利用APIについて
```
About
Open-Meteo is an open-source weather API
and offers free access for non-commercial use.
No API key is required. You can use it immediately!
```

https://open-meteo.com/en/about

```
License
API data are offered under Attribution 4.0 International (CC BY 4.0)
You are free to share: copy and redistribute the material in any medium or format
and adapt: remix, transform, and build upon the material.

Attribution: You must give appropriate credit, provide a link to the license,
and indicate if changes were made.
You may do so in any reasonable manner,
but not in any way that suggests the licensor endorses you or your use.

You must include a link next to any location,
Open-Meteo data are displayed like:

<a href="https://open-meteo.com/">Weather data by Open-Meteo.com</a>

Open-Meteo is open-source
Source code is available on GitHub
under the GNU Affero General Public License Version 3 AGPLv3
or any later version. You can find the license here.
```

https://open-meteo.com/en/license

上記の通り、出典の明記を求められている以外は利用の自由度が高いAPIとなっております。
＃3/26 15:29修正。誤字指摘ありがとうございます。

## ソースについて

<details><summary>htmlについて</summary>

🔹1. !DOCTYPE html, lang="ja"
```html
<!DOCTYPE html>
<html lang="ja">
```
日本語指定のHTML5文書
lang="ja"により日本語環境に適した表示に

🔹2. head セクション
```html
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>週間予報アプリ</title>
    <link rel="stylesheet" href="style.css">
</head>
```
- meta charset="UTF-8"
文字エンコーディングを UTF-8 に設定
日本語の文字化けを防ぐ ために必須。
- meta name="viewport" content="width=device-width, initial-scale=1.0"
スマホ対応のレスポンシブデザインを有効化
width=device-width → 画面サイズに合わせる
initial-scale=1.0 → 初期倍率を1倍にする
- title
ブラウザのタブに表示されるページタイトル
- link rel="stylesheet" href="style.css"
CSS ファイル (style.css) を適用
ページの見た目を整えるために使用

🔹3. body セクション
```html
<div class="app-container">
```
container クラスで全体を囲むことでアプリ全体のラッパー（中央寄せ、パディング）

🔹4. ロケーション選択 & 予報取得ボタン
```html
<select id="location-select">...</select>
<button id="fetch-button">予報取得</button>
```
- select
都道府県庁所在地の選択用のドロップダウンリスト
- button
クリックすると、天気予報を取得
script.js 内のイベントで処理。

🔹5. 天気予報の表示エリア
```html
<div id="weather-container"></div>
```
- 1週間分の天気予報の情報を表示するボックス
- script.js で内容が更新される。

🔹6. フッター
```html
<footer class="footer">...</footer>
```
- Open-Meteoの利用規約に沿ったデータ出典と参考リンク表記

</details>

---

<details><summary>jsについて</summary>

🔹1. 緯度経度リスト
```js
const locations = {
    "東京都 - 新宿区": { lat: 35.689501, lon: 139.691722 },
    ...
};
```

- 全国47都道府県の庁所在地を緯度・経度で定義
- プルダウンに使われ、API呼び出しに必要な座標情報

🔹2. 初期化処理

```js
Object.keys(locations).forEach(loc => {
    const option = ...
    select.appendChild(option);
});
select.value = "東京都 - 新宿区";
```

- プルダウンに都道府県名を追加
- デフォルトは「東京都 - 新宿区」

🔹3. ボタンによるAPI呼び出し＋インターバル

```js
button.addEventListener('click', () => {
    button.disabled = true;
    ...
    fetchWeather();
    setTimeout(() => { ... }, 3000);
});
```

- ボタン押下 → API呼び出し → ボタンを3秒間無効にして連打防止

🔹4. Open-Meteo APIから天気取得

```js
function fetchWeather() {
    const url = `https://api.open-meteo.com/v1/forecast?...`;
    fetch(url).then(res => res.json()).then(data => {
        // 各日ごとのデータを展開
    });
}
```

- APIから「7日分の最高・最低気温、天気コード」を取得
- 各日の天気を1行ずつ作成し、.weather-day-rowに格納

🔹5. 日付フォーマット

```js
function formatDateFull(dateStr) {
    const weekdays = ['日', '月', ...];
    return `${月}/${日}　${曜日}`;
}
```

🔹6. 天気コード → 日本語表現
```js
function weatherDescription(code) {
    const map = {
        0: '快晴',
        1: 'ほぼ晴れ'
        // コード値を日本語にマップ
    }
    return map[code] || `コード${code}：不明`;
}
```

- 公式weathercodeに対応した日本語表現（例：66 → 弱い凍結雨）

🔹7. 天気コード → 絵文字
```js
function getWeatherEmoji(code) {
    if (code === 99) return '⛈️🧊🧊';       // 雷雨（強い雹）
    return '❔';
}
```
- Open-Meteoの全コード（0〜99）に対して、それっぽい絵文字を割り当て

</details>

---

<details><summary>cssについて</summary>

🔹1. 全体スタイル
```css
body {
    background-color: #1e1e1e;
    color: #ffffff;
}
```
- ダークテーマベース
- フォント・背景・文字色などを統一

🔹2. コントロールパネル（プルダウン＋ボタン）
```css
.control-panel {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5em;
}
button.disabled {
    background-color: #555;
    opacity: 0.6;
}
```
- 配置の整列、非活性化スタイル、ホバー効果など

🔹3. 天気行レイアウト（1行7列）

```css
.weather-day-row {
    display: flex;
    justify-content: space-between;
}
.weather-col {
    min-width: 3em;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
```
- 1行に対して「日付｜曜日｜天気｜絵文字｜最低｜/｜最高」の7列
- tabular-nums で数字の桁幅が揃い、きれいに見える

🔹4. フッター
```css
.footer {
    font-size: 0.9em;
    color: #aaa;
    text-align: center;
}
```
- Open-Meteo表記＆Qiita記事リンクも柔らかいトーンで

</details>

---

## フロー図

```mermaid
sequenceDiagram
    participant User as 利用者（スマホ）
    participant GitHub as GitHub Pages（ホスティング）
    participant OpenMeteo as OpenMeteo

    User->>GitHub: スマホでアクセス
    GitHub-->>User: HTML, CSS, JavaScript を取得
    User->>User: JavaScriptを実行（スマホ上）

    User->>OpenMeteo: 緯度経度を含めてAPIにJSONリクエスト
    OpenMeteo-->>User: JSONレスポンス（天気データ）

    User->>User: 画面作成 & 天気情報を表示

```
---

:::note info
気象庁のjsonを利用した天気予報もやってみたので、良ければご確認ください。

https://qiita.com/kubo4ka/items/9b7fbeca3e28599d8bc0

:::

## 仕様、制限、限界
＃3/26　19:31追記
- 経度緯度がスタティック、ハードコード
例えば庁舎移転や市区町村合併などがあると、プルダウンの内容が陳腐化してしまいます。
今回利用しているOpenMeteoのAPIは、経度緯度を渡す必要があるため、
何らかの経度緯度を動的に、何らかのAPIで取得したい、
それをプルダウンにしたい、というのが最初に思ったことです。
庁舎、駅、観光名所など、何らかの全国的な経度緯度を取得できないかと検討しましたが、
今回は上手くまとまらず見送りました。
他にも、地図を表示し、任意の地点にピンを立てて、
その経度緯度に対してリクエストする、
或いはスマホの位置情報を利用するなど、
アイディアは出ましたが、
今回はスタティック、ハードコードで先ずは完成としました。
- カラム、整列がイメージ通りに行っていない
もっとエクセルのようなイメージでやろうとしましたがガタついています。
素直にHTMLテーブルを検討した方が良かったかも知れませんが、
今回はこの並びで完成としました。

:::note info
3/29追記　地図を利用した天気予報もやってみたので、良ければご確認ください。

https://qiita.com/kubo4ka/items/7128a8040ac257a6c039

:::

以上