0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Angular】お天気アプリを開発してみた ‐ 開発備忘録 #2

Posted at

こんにちは、Smart Designの伊藤です。
前回の記事(開発備忘録 #1)では、Angularを使ってお天気アプリを開発するための事前準備を紹介しました。
今回はその続編として、

  • 取得した天気データとそのグラフの表示(Chart.js)

を中心に紹介していきます。

5.グラフで天気を可視化

天気予報といえば、数値だけでなく「視覚的なグラフ表示」があると分かりやすくなりますよね。このアプリでも、Chart.js を用いて、天気データ(気温)を折れ線グラフで可視化する機能を実装しました。
ここでは、
 ・どのような手順で天気情報を取得しグラフ表示しているか

 ・使用しているコンポーネントとその役割

 ・各コンポーネントで実行している処理

について解説します。

実際の画面
スクリーンショット 2025-05-27 130532.png


5-1.表示までの流れ

1.weather.componentがフォームから都市名を受け取る

2.weather.service.tsで OpenWeatherMap API にリクエストを送り、天気データを取得

3.取得データを整形し、テンプレートで表示

4.同時にweather-chart.componentに気温の時系列データを渡し、グラフ表示を行う


5-2. コンポーネント

weather.component(親)

ファイル 説明
weather.component.ts ユーザーの入力(都市名)を受け取り、APIリクエストを実行。結果データをテンプレートと子コンポーネントへ渡す。
weather.component.html 検索フォームと天気データ表示、 を配置し、チャートデータを渡す。

weather-chart.component(子)

ファイル 説明
weather-chart.component.ts @ Input() で受け取った気温データを元に Chart.js グラフを描画。※ここで表記されているInput()は、リンクを消すためにわざとスペースを入れています
weather-chart.component.html Chart.js コンポーネントをテンプレート内に定義。

weather.service.ts(サービス)

ファイル 説明
weather.service.ts OpenWeatherMap API など外部APIとの通信を担う。HttpClient を用いて天気データを取得し、Observable で返す。

5-3.各コンポーネントの処理の流れ

weather.component.ts

weather.component.ts
export class WeatherComponent {
  weatherData: any;
  chartData: number[] = [];
  chartLabels: string[] = [];

  constructor(private weatherService: WeatherService) {}

  search(city: string) {
    this.weatherService.getWeather(city).subscribe(data => {
      this.weatherData = data;

      // グラフ用のデータ抽出(例: 3時間ごとの気温)
      this.chartLabels = data.list.map((item: any) =>
        new Date(item.dt_txt).getHours() + ''
      );
      this.chartData = data.list.map((item: any) =>
        Math.round(item.main.temp)
      );
    });
  }
}

WeatherComponent で行っている処理

このコンポーネントは、天気検索とグラフ表示の中核的な役割を担っています。主な処理の流れは以下の通りです:

1. ユーザーが都市名を入力して検索を実行
search(city: string) メソッドが呼び出され、入力された都市名を引数に WeatherService を通じて API リクエストを送信。

2. 取得した天気データを受け取り保持
this.weatherData に API から返された天気予報(5日分/3時間刻みのデータ)をそのまま保持。

3. グラフ描画用のデータを抽出・整形
chartLabels: 各予報の時刻を「○時」の形式に変換し、横軸のラベルとして使う。
chartData: 各予報時点の気温を取り出して、縦軸のデータセットとして使用。

これらはそのまま子コンポーネントの weather-chart に渡され、グラフ表示に利用されます。

weather.component.html

html
<form (ngSubmit)="search(cityInput.value)">
  <input #cityInput type="text" placeholder="都市名を入力" />
  <button type="submit">検索</button>
</form>

<!-- 天気の概要表示 -->
<div *ngIf="weatherData">
  <h2>{{ weatherData.city.name }} の天気</h2>
  <p>現在の気温: {{ weatherData.list[0].main.temp }}℃</p>

  <!-- グラフ表示コンポーネント -->
  <app-weather-chart
    [labels]="chartLabels"
    [data]="chartData">
  </app-weather-chart>
</div>

weather.component.html の構成と処理の流れ

1. 天気検索フォーム

html
<input type="text" [(ngModel)]="city" placeholder="都市名を入力" />
<button (click)="search(city)">検索</button>
  • 双方向バインディング([(ngModel)]) により、入力欄と city 変数が常に同期
  • 検索ボタン押下で search() メソッドを呼び出し、APIリクエストを実行

2. 天気情報の表示(検索結果)

html
<div *ngIf="weatherData">
  <h2>{{ weatherData.city.name }} の天気</h2>
  <ul>
    <li *ngFor="let item of weatherData.list.slice(0, 5)">
      {{ item.dt_txt }} - {{ item.weather[0].description }} - {{ item.main.temp }}°C
    </li>
  </ul>
</div>
  • *ngIf で天気データがある場合のみ結果を表示
  • *ngFor で最初の数件(例:5件)の予報を簡易表示
  • 日時・天気概要・気温 をシンプルに出力

3. グラフコンポーネントの表示

html
<app-weather-chart
  [labels]="chartLabels"
  [data]="chartData">
</app-weather-chart>
  • 子コンポーネント WeatherChartComponent をテンプレート内に配置
  • @Input() で渡された labels(時刻ラベル)と data(気温データ)を使ってグラフを描画

weather-chart.component.ts

weather-chart.component.ts
import { Component, Input, OnChanges } from '@angular/core';

@Component({
  selector: 'app-weather-chart',
  templateUrl: './weather-chart.component.html',
  styleUrls: ['./weather-chart.component.css']
})
export class WeatherChartComponent implements OnChanges {
  @Input() data: number[] = [];
  @Input() labels: string[] = [];

  public chart: any;

  ngOnChanges() {
    this.renderChart();
  }

  renderChart() {
    this.chart = {
      type: 'line',
      data: {
        labels: this.labels,
        datasets: [{
          label: '気温 (℃)',
          data: this.data,
          borderColor: 'rgba(75, 192, 192, 1)',
          fill: false,
        }]
      },
      options: {
        responsive: true,
        plugins: {
          legend: { display: true },
        },
        scales: {
          y: {
            beginAtZero: false
          }
        }
      }
    };
  }
}

weather-chart.component.ts の処理

このコンポーネントは、親コンポーネントから渡された天気データをグラフで可視化する専用パーツです。表示ロジックに特化し、グラフ描画を担当します。

主な役割と処理

weather-chart.component.ts
@Input() labels: string[] = [];
@Input() data: number[] = [];
  • 親コンポーネント(WeatherComponent)から、グラフのラベル(時刻)とデータ(気温)を受け取る
  • @Input() デコレーターで双方向バインディングなしに受け取る「受信専用プロパティ」を定義

グラフライブラリへのデータ提供

weather-chart.component.ts
chartOptions = {
  responsive: true,
  plugins: { legend: { display: false } }
};

chartData = [{ data: [], label: '気温' }];
chartLabels: string[] = [];
  • ngOnChanges() などで @Input() で受け取ったデータを、グラフ用の構造に整形
  • 使用しているグラフライブラリ(Chart.js、ng2-charts)に合わせた構造へ変換して渡す

weather-chart.component.html

weather-chart.component.html
<canvas baseChart
  [data]="chart.data"
  [type]="chart.type"
  [options]="chart.options">
</canvas>

このテンプレートは、グラフライブラリ(Chart.js + ng2-charts)を使って気温の変化を可視化するビューです。描画部分は非常にシンプルながら、動的なデータバインディングに対応しています。

処理のポイント

  • baseChart ディレクティブは、ng2-charts ライブラリのコンポーネント機能
  • [data]:グラフに表示する系列データ(例:気温)をバインド
  • [type]:グラフの種類(例:'line', 'bar' など)を指定
  • [options]:凡例や軸の表示設定などの各種カスタマイズオプション

データの流れ

  1. weather.component.ts で都市の天気データを取得
  2. weather-chart.component.ts@Input() を通じて受け取ったデータを chart.data に変換
  3. テンプレートの <canvas baseChart> に反映され、気温のグラフが自動描画される

weather.service.ts

weather.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';

@Injectable({
  providedIn: 'root'
})
export class WeatherService {
  private apiUrl = 'https://api.openweathermap.org/data/2.5/forecast';

  constructor(private http: HttpClient) {}

  getWeather(city: string): Observable<any> {
    return this.http.get(this.apiUrl, {
      params: {
        q: city,
        units: 'metric',
        appid: environment.weatherApiKey
      }
    });
  }
}

天気データを取得するサービス:WeatherService

WeatherService は、アプリケーション内の他のコンポーネントから呼び出され、OpenWeatherMap の天気予報 API にアクセスして天気情報を取得するサービスです。HTTP通信の実装を専用のクラスに分離することで、保守性とテスト性が向上します。

主な役割と処理
1.サービスとしてアプリに登録

weather.service.ts
@Injectable({ providedIn: 'root' })
  • この1行で、アプリ全体でこのサービスをシングルトンとして利用可能にした
  • 各コンポーネントで DI(依存性注入)を通じて呼び出すだけで使える

2.HTTP通信の実装

weather.service.ts
constructor(private http: HttpClient) {}
  • Angular の HttpClient を使って外部 API にアクセス
  • 必要なモジュールは HttpClientModuleAppModule にインポートして使用

3.天気APIの呼び出し

weather.service.ts
getWeather(city: string): Observable<any> {
  return this.http.get(this.apiUrl, {
    params: {
      q: city,
      units: 'metric',
      appid: environment.weatherApiKey
    }
  });
}
  • city を引数に取り、OpenWeatherMap API に GET リクエストを送信
  • メトリック単位(摂氏)で取得し、APIキーは環境変数 environment.weatherApiKey から安全に参照
  • 戻り値は Observable<any> 型で返却され、呼び出し元(コンポーネント)で .subscribe() によって非同期的に取得・処理

5-4.まとめ

このように、親コンポーネントでAPIから取得した天気データを加工し、子コンポーネントに渡すことで、Angularらしい責務分離と再利用性のある設計が実現できました。

  • データ取得はサービス層に集約(weather.service.ts

  • 表示とグラフ描画はコンポーネントごとに責任分担

  • @Input() によるデータの受け渡しで柔軟な連携

次回は、検索履歴の保存や、位置情報との連携について掘り下げていきます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?