APIから気象情報を取得してグラフ化

#はじめに
OpenWeatherMapAPIから気象情報を取得してChart.jsを使ってグラフ化してみました。
例として、「現在の時刻から24h後までの東京都の気温の変化」を取得します。

環境
- Laravel6系(PHP)
- OpenWeatherMapAPI
- Chart.js(JavaScriptライブラリ)


##ソースコード例
```ChartController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ChartController extends Controller
{
    public function index() 
    {
        // 天気API取得のための情報準備
        $weatherConfig = array(
            'appid' => '各自で取得',
            'lat' => '26.231408',  //沖縄の那覇市の緯度
            'lon' => '127.685525',  //沖縄の那覇市の経度
        );
        // 天気API取得とJSONデコード
        $weatherJson = file_get_contents('http://api.openweathermap.org/data/2.5/onecall?lat=' . $weatherConfig['lat'] . '&lon=' . $weatherConfig['lon'] . '&units=metric&lang=ja&APPID=' . $weatherConfig['appid']);
        $weatherData = json_decode($weatherJson, true);

        $hour = [];
        $temp = [];
        $dayLabels = [];
        $tempData = [];
        $weatherViewData = array();
       
        // 1時間毎の天気の情報全て
        $weatherHours = $weatherData['hourly'];
        foreach($weatherHours as $weatherHour) {
            // 時間のラベル・気温のデータを取得
            $dayLabels[] = date('m/d:H時', $weatherHour['dt']);
            $tempData[] = $weatherHour['temp'];

            $weatherViewData['dayLabels'] = $dayLabels;
            $weatherViewData['temp'] = $tempData;
        }
        // JSへ渡すためにエンコード
        $weatherViewData = json_encode($weatherViewData);

        return view('chart', ['weatherViewData' => $weatherViewData]);
    }
}
```

##解説
###OpenWeatherMapAPIを取得

```.php
        // 天気API取得のための情報準備
        $weatherConfig = array(
            'appid' => '各自で取得',
            'lat' => '26.231408',  //沖縄の那覇市の緯度
            'lon' => '127.685525',  //沖縄の那覇市の経度
        );
        // 天気API取得とJSONデコード
        $weatherJson = file_get_contents('http://api.openweathermap.org/data/2.5/onecall?lat=' . $weatherConfig['lat'] . '&lon=' . $weatherConfig['lon'] . '&units=metric&lang=ja&APPID=' . $weatherConfig['appid']);
        $weatherData = json_decode($weatherJson, true);
```


APIのidの取得は公式HPで登録するだけでOK.
https://openweathermap.org/
idの取得はこのブログが参考になる。
https://yuukiyg.hatenablog.jp/entry/2019/11/17/182410

緯度と経度は今回予め指定しているがフォームなどから取得しても良いし、APIのURLを変更すれば緯度・経度からではなく「東京都」のような都道府県名から取得することもできる。（割愛)
JSONとして受け取るため、デコードが必要になる。

###受け取ったJSONのデータを整形

```.php
        // 1時間毎の天気の情報全て
        $weatherHours = $weatherData['hourly'];
        foreach($weatherHours as $weatherHour) {
            // 時間のラベル・気温のデータを取得
            $dayLabels[] = date('m/d:H時', $weatherHour['dt']);
            $tempData[] = $weatherHour['temp'];

            $weatherViewData['dayLabels'] = $dayLabels;
            $weatherViewData['temp'] = $tempData;
        }
        // JSへ渡すためにエンコード
        $weatherViewData = json_encode($weatherViewData);
```
JSONのデータをvar_dump()して頂くと分かるが、時間、気温、天候、天気を示すアイコンなど様々なものがJSONで取得できている。今回は一時間毎の気温を取得したいので、このような整形をしていて、最後にPHPからJavaScriptへ渡したいのでエンコードしている。

###Chart.jsを使ったグラフの表示
表示部分に関わる部分のコードを抜粋↓

```chart.blade.php
<head>
...(割愛)
    <!-- chart.jsのCDN--> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.js">
</head>
    <body>
        <h1>気温グラフ</h1>
        <canvas id="chart"></canvas>
        <script>
        var weatherViewData = JSON.parse('<?php echo $weatherViewData; ?>'); // JSONデコード
        var ctx = document.getElementById("chart");

        var chart = new Chart(ctx, {
            type: 'line',
            data: {
                labels: weatherViewData['dayLabels'],
                datasets: [
                    {
                    label: '気温',
                    data: weatherViewData['temp'],
                    borderColor: 'rgba(255,0,0,1)',
                    backgroundColor: 'rgba(0,0,0,0)'
                    },
                    // {
                    // * 複数のデータを追加可能
                    // },
                ],
            },
            options: {
                title: {
                    display: true,
                    text: '気温'
                },
                scales: {
                    yAxes: [{
                    ticks: {
                        suggestedMax: 20,
                        suggestedMin: 0,
                        stepSize: 5,
                        callback: function(value, index, values){
                        return  value +  '度'
                        }
                    }
                    }]
                },
            }
        });

    </body>
```
### Chart.jsをCDNでネットワーク経由で利用
```.html
<head>
...(割愛)
    <!-- chart.jsのCDN--> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.js">
</head>
```
今回はCDNを使用。headタグの中にscriptを埋め込んでいる。
CDNを使う場合は、下記のURLからURLを取得できる。
https://cdnjs.com/libraries/Chart.js
もちろんnpmでのインストールでもOK。

### グラフ表示エリア
```.html
  <canvas id="chart"></canvas>
```
HTML5から導入されたcanvasタグでグラフの表示エリアを指定。


### Chart.jsの基本の使い方

```.js
   var weatherViewData = JSON.parse('<?php echo $weatherViewData; ?>');
   var ctx = document.getElementById("chart");
   var chart = new Chart(ctx, { 
   }
```
PHPから渡ってきた$weatherViewDataをパースして、JavaScriptの変数weatherViewDataへ格納。
canvas要素のchartのidを指定して、Chartのライブラリを使っていく。

### 描画するグラフの値の設定

```.js
        var chart = new Chart(ctx, {
            type: 'line',
            data: {
                labels: weatherViewData['dayLabels'],
                datasets: [
                    {
                      label: '気温',
                      data: weatherViewData['temp'],
                      borderColor: 'rgba(255,0,0,1)',
                      backgroundColor: 'rgba(0,0,0,0)'
                    },
                 // {
                 // * 複数のデータを追加可能
                 // },
                ],
            },
            options: {
                title: {
                    display: true,
                    text: '気温'
                },
                scales: {
                    yAxes: [{
                    ticks: {
                        suggestedMax: 20,
                        suggestedMin: 0,
                        stepSize: 5,
                        callback: function(value, index, values){
                        return  value +  '度'
                        }
                    }
                    }]
                },
            }
```
基本的にはtype, data, optionsを指定すればグラフは描けた。
dataの中でPHPから渡ってきた変数を使っている。

・type => 今回は折れ線グラフを使用するために「line」を使用。
・data => dataの中にlabelとdatasetを記入する。
・options => オプションなので、グラフのタイトルや、Y軸のパラメータなどを指定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969534/d4fa8a94-39a6-9462-eb81-ad17fdbc24b7.png)



下記の記事が参考になる。
https://qiita.com/Haruka-Ogawa/items/59facd24f2a8bdb6d369#2-%E8%A8%98%E8%BF%B0%E5%BD%A2%E5%BC%8F

Chart.jsでは他にも様々なグラフが書けるようなので挑戦してみたい。