PHPで地図で指定した場所の気圧予報を求める

(1/1)
日本気象協会では、生活に密接な情報として気圧変化についても公表している。「PHPで天気予報を求める」などでは気象庁の「気象庁防災情報XML」を利用して天気予報などを行ったが、気象庁が提供する気圧予報情報はビジネス向けサービスとして有償になる。そこで、気圧予報を行うために、全世界の気象予報情報を無償提供している OpenWeather を利用することにした。気象庁が提供する気圧予報情報とは異なることにご留意いただきたい。
例によって、地図サービスをクラウド連携することで、住所やランドマークから今後5日間の気圧と、降水量・気温・風力から1つを選んでグラフ表示する。

サンプル・プログラムの実行例

PHPで地図で指定した場所の気圧予報を求める
Googleマップ表示

目次

サンプル・プログラムのダウンロード

圧縮ファイルの内容
pressureForecast.phpサンプル・プログラム本体
weatherIcons\*.png天気予報アイコン
.pahooEnvクラウドサービスを利用するためのアカウント情報などを記入する .env ファイル。
使い方は「各種クラウド連携サービス(WebAPI)の登録方法」を参照。include_path が通ったディレクトリに配置すること。
pahooInputData.phpデータ入力に関わる関数群。
使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。
pahooGeoCode.php住所・緯度・経度に関わるクラス pahooGeoCode。
使い方は「PHPで住所・ランドマークから最寄り駅を求める」「PHPで住所・ランドマークから緯度・経度を求める」などを参照。include_path が通ったディレクトリに配置すること。
pahooWeather.php気象情報に関わるクラス pahooWeather。
気象情報に関わるクラスの使い方は「PHPで天気予報を求める」を参照。include_path が通ったディレクトリに配置すること。
pressureForecast.php 更新履歴
バージョン 更新日 内容
1.0.1 2026/03/10 Yahoo!ジオコーディングが利用できない不具合を修正
1.0.0 2026/03/07 初版
pahooGeoCode.php 更新履歴
バージョン 更新日 内容
6.10.0 2026/02/19 getLocalGovernmentCode, address2LocalGovernmentCode, localGovernmentCode2addresss メソッド追加
6.9.1 2025/11/25 PHP8.5対応:double→float
6.9.0 2025/09/21 jsPolygon, jsPolygon_Gmap, jsPolygon_Leaflet, loadGeoJSON, getPrefBorderList を追加
6.8.0 2025/08/10 アクセスキーなどを ".pahooEnd" に分離
6.7.1 2025/07/26 jsLine_Gmap() - bug-fix
pahooWeather.php 更新履歴
バージョン 更新日 内容
5.9.0 2026/03/07 currentWeatherOpenWeather, utc2jst, kelvin2celsius, addOpenWeatherCounterメソッド追加
5.8.0 2026/02/15 getPollenメソッド追加
5.7.0 2025/08/09 readEnvWBGTinfoSpots(), readEnvWBGTforecast(), getWBGTcolor() 追加
5.6.2 2025/04/10 readJmaSpots() -- bug-fix
5.6.1 2025/04/08 getMyscriptPathURL() -- bug-fix

サンプル・プログラムの流れ

PHPで地図で指定した場所の気圧予報を求める
プログラムの流れは「PHPで最寄り駅を求める」の時と同じで、緯度・経度から施設情報を求める部分を、「PHPで天気予報を求める」に差し替えただけである。

準備:PHP の https対応

クラウド連携や相手先サイトのデータを読み込むのに https通信を使うため、PHPに OpenSSLモジュールが組み込まれている必要がある。関数  phpinfo  を使って、下図のように表示されればOKだ。
OpenSSL - PHP
そうでない場合は、次の手順に従ってOpenSSLを有効化し、PHPを再起動させる必要がある。

Windowsでは、"php.ini" の下記の行を有効化する。
extension=php_openssl.dll
Linuxでは --with-openssl=/usr オプションを付けて再ビルドする。→OpenSSLインストール手順

これで準備は完了だ。

準備:pahooInputData 関数群

PHPのバージョンや入力データのバリデーションなど、汎用的に使う関数群を収めたファイル "pahooInputData.php" が同梱されているが、include_path が通ったディレクトリに配置してほしい。他のプログラムでも "pahooInputData.php" を利用するが、常に最新のファイルを1つ配置すればよい。

また、各種クラウドサービスに登録したときに取得するアカウント情報、アプリケーションパスワードなどを登録した .pahooEnv ファイルから読み込む関数 pahooLoadEnv を備えている。こちらについては、「各種クラウド連携サービス(WebAPI)の登録方法」をご覧いただきたい。

準備:pahooGeoCode クラス

pahooGeoCode.php

  41: class pahooGeoCode {
  42:     public $items;      // 検索結果格納用
  43:     public $error;      // エラー・フラグ
  44:     public $errmsg;     // エラー・メッセージ
  45:     public $hits;       // 検索ヒット件数
  46:     public $webapi; // 直前に呼び出したWebAPI URL
  47: 
  48:     // 都道府県境界線データ
  49:     // SimpleMaps.com is a product of Pareto Software, LLC. © 2010-2025
  50:     // https://simplemaps.com/gis/country/jp
  51:     // ※各自の環境に合わせて設定すること
  52:     public $GeoJsonJP = __DIR__ . '/jp.json';
  53: 
  54:     // -- 以下のデータは .env ファイルに記述可能
  55:     // Google Cloud Platform APIキー
  56:     // https://cloud.google.com/maps-platform/
  57:     // ※Google Maps APIを利用しないのなら登録不要
  58:     public $GOOGLE_API_KEY_1 = '';      // HTTPリファラ用
  59:     public $GOOGLE_API_KEY_2 = '';      // IP制限用
  60:     public $GOOGLE_MAP_ID    = '';      // GoogleMaps ID
  61: 
  62:     // Yahoo! JAPAN Webサービス アプリケーションID
  63:     // https://e.developer.yahoo.co.jp/register
  64:     // ※Yahoo! JAPAN Webサービスを利用しないのなら登録不要
  65:     public $YAHOO_APPLICATION_ID = '';
  66: 
  67:     // OSM Nominatim Search API利用時に知らせるメールアドレス
  68:     // https://wiki.openstreetmap.org/wiki/JA:Nominatim#.E6.A4.9C.E7.B4.A2
  69:     // ※OSM Nominatim Search APIを利用しないのなら登録不要
  70:     public $NOMINATIM_EMAIL = '';
  71: 
  72:     // IP2Location.io APIキー
  73:     // https://www.ip2location.io/
  74:     // ※IP2Location.ioを利用しないのなら登録不要
  75:     public $IP2LOCATION_API_KEY = '';

GoogleマップやLeafletなどによる地図描画や住所検索を行うためのクラスが pahooGeoCode である。同梱のクラス・ファイル "pahooGeoCode.php" は include_path が通ったディレクトリに配置してほしい。他のプログラムでも pahooGeoCodeクラス を利用するが、常に最新のクラス・ファイルを1つ配置すればよい。

地図や住所検索として Google を利用するのであれば Google Cloud Platform APIキーマップID が必要で、その入手方法は「Google Cloud Platform - WebAPIの登録方法」を、Yahoo!JAPAN を利用するのであれば Yahoo! JAPAN Webサービス アプリケーションIDが必要で、その入手方法は「Yahoo!JAPAN デベロッパーネットワーク - WebAPIの登録方法」を、IP2Location.ioを利用するのであれば「PHPでIPアドレスやホスト名から住所を求める」を、それぞれ参照されたい。

PHPのクラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。

myWeather.php

  72: // 地図描画サービスの選択
  73: //    0:Google
  74: //    2:地理院地図・OSM
  75: define('MAPSERVICE', 2);
  76: 
  77: // 住所検索サービスの選択
  78: //    0:Google
  79: //    1:Yahoo!JAPAN
  80: //   11:HeartRails Geo API
  81: //   12:OSM Nominatim Search API
  82: //   13:国土地理院ジオコーディングAPI
  83: define('GEOSERVICE', 1);
  84: 
  85: // 逆ジオコーディングサービスの選択
  86: //    0:Google
  87: //    1:Yahoo!JAPAN
  88: //   11:HeartRails Geo API
  89: //   21:簡易ジオコーディングサービス
  90: define('REVGEOSERVICE', 1);

表示する地図は、Googleマップ地理院地図・オープンストリートマップ(OSM)から選べる。あらかじめ、定数 MAPSERVIC に値を設定すること。
住所検索サービスは、GoogleYahoo!JAPANHeartRails Geo APIOSM Nominatim Search API国土地理院ジオコーディングAPI から選べる。あらかじめ、定数 GEOSERVICE に値を設定すること。
逆ジオコーディングサービスは、GoogleYahoo!JAPANHeartRails Geo API簡易ジオコーディングサービスから選べる。あらかじめ、定数 REVGEOSERVICE に値を設定すること。

準備:pahooWeather クラス

pahooWeather.php

  16: class pahooWeather {
  17:     // 予報値地点情報ファイル(出力)
  18:     const FILE_JMASPOTS = 'jmaweatherspots.xml';
  19:     // 予報値地点情報ファイルのバージョン
  20:     const FILE_VERSION = '2.2';
  21:     // 予報値地点情報ファイルを再作成するサイクル(単位:時)
  22:     const INTERVAL_READJMASPOTS = (24 * 7);
  23:     // 予報地点情報ファイルを作成するスクリプト
  24:     const URL_JMPWEATHERINIT = 'jmaWeatherInit.php';
  25: 
  26:     // 気象庁防災情報XML:長期フィード - 定時配信
  27:     const FEED_REGULAR_L = 'https://www.data.jma.go.jp/developer/xml/feed/regular_l.xml';
  28: 
  29:     // 環境省:暑さ指数(WBGT)情報提供地点情報ファイル
  30:     const FILE_WBGTINFO_SPOTS = 'envWBGTinfoSpots.xml';
  31: 
  32:     public $jmaWeeklyWeather;   // 天気予報情報(配列)
  33:     public $spots;              // 予報地点情報(配列)
  34:     public $envWBGTinfoSpots;   // 暑さ指数(WBGT)情報
  35:     public $xmlfile;            // 直前に呼び出したXMLファイルのURL(配列)
  36:     public $error;              // エラーフラグ
  37:     public $errmsg;             // エラーメッセージ
  38:     public $pcc;                // pahooCacheオブジェクト
  39:     public $webapi;             // 直前に呼び出したWebAPI
  40: 
  41:     // OpenWeather APIキー
  42:     // https://home.openweathermap.org/users/sign_in
  43:     // ※OpenWeatherサービスを利用しないのなら登録不要
  44:     public $OPENWEATHER_APIKEY = '';
  45:     // OpenWeather API呼び出しカウンター・ファイル名
  46:     public $OPENWEATHER_COUNTER_FILE = __DIR__ . '/openWeatherCounter.json';
  47:     // OpenWeather APIの 1分間あたり呼び出し回数の上限
  48:     public $OPENWEATHER_REQUEST_MAX = 30;
  49: 
  50: /**
  51:  * コンストラクタ
  52:  * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-72-01.shtm
  53:  * @param   object $pcc pahooCacheオブジェクト
  54:  * @return  なし
  55: */
  56: function __construct($pcc=NULL) {
  57:     $this->error   = FALSE;
  58:     $this->errmsg  = '';
  59:     $this->spots   = array();
  60:     $this->xmlfile = array('', '', '', '');
  61:     $this->pcc     = $pcc;
  62:     $this->webapi  = '';
  63: 
  64:     // PHPバージョンチェック
  65:     if (! $this->isphp5over()) {
  66:         $this->error   = TRUE;
  67:         $this->errmsg  = '動作にはPHP5以上が必要です';
  68:     }
  69: 
  70:     // 予報地点情報を読み込む
  71:     $this->readJmaSpots();
  72: 
  73:     // OpenWeather APIキー
  74:     if (isset($_ENV['PAHOO_OPENWEATHER_APIKEY'])) {
  75:         $this->OPENWEATHER_APIKEY = $_ENV['PAHOO_OPENWEATHER_APIKEY'];
  76:     }
  77: }

気象庁防災情報XML 等を利用し、天気予報、暑さ指数(WBGT)、花粉飛散数データ、気圧予報などを行うためのクラスが pahooWeather である。同梱のクラス・ファイル "pahooWeather.php" は include_path が通ったディレクトリに配置してほしい。他のプログラムでも pahooWeatherクラス を利用するが、常に最新のクラス・ファイルを1つ配置すればよい。

天気予報として OpenWeather を利用するのであれば OpenWeather APIキー が必要で、その入手方法は「OpenWeather - WebAPIの登録方法」を参照されたい。

PHPのクラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。

準備:JpGraphライブラリ

pressureForecast.php

  67: // JpGraph:include_pathが通ったディレクトリに配置
  68: require_once('jpgraph/jpgraph.php');
  69: require_once("jpgraph/jpgraph_iconplot.php");
  70: require_once('jpgraph/jpgraph_line.php');
  71: require_once('jpgraph/jpgraph_bar.php');
  72: require_once('jpgraph/jpgraph_plotline.php');
  73: 

国内ではアシアル株式会社がサポートしている PHPで様々なグラフを生成するライブラリ「JpGraph」を準備する。JpGraph コミュニティ版は、QPL (Qt Free License) 1.0 ライセンスの下で、非営利目的で使用する場合に無償利用できる。
JpGraph は、サーバ側(PHP側)でグラフを画像データとして生成し、クライアントへ配信する。このため、GDライブラリが有効化されていることが前提である。
また、使用する機能によってインクルードする PHPファイルの種類が異なることに留意してほしい。

公式サイトからダウンロードしたファイルを解凍したら、include_path が通ったディレクトリに配置してほしい。

凡例やラベルに日本語を使う場合は、日本語フォント(TrueTypeファイル)を用意しておく。これについても、アシアル社のサイトに詳しい説明がある。
具体的には、フォント・ファイルを格納したフォルダを "jpg-config.inc.php" の定数 TTF_DIR および MBTTF_DIR に設定してやる。
実際に使うフォントは "jpgraph_ttf.inc.php" の定数 MINCHO_TTF_FONTPMINCHO_TTF_FONTGOTHIC_TTF_FONTPGOTHIC_TTF_FONT に設定されている。デフォルトで設定されているのは IPA の無償フォントで、文字情報技術促進協議会の IPAフォントから入手できる。

解説:各種定数

pressureForecast.php

  74: // 各種定数(START) ===========================================================
  75: 
  76: // 地図描画サービスの選択
  77: //    0:Google
  78: //    2:地理院地図・OSM
  79: define('MAPSERVICE', 2);
  80: 
  81: // 住所検索サービスの選択
  82: //    0:Google
  83: //    1:Yahoo!JAPAN
  84: //   11:HeartRails Geo API
  85: //   12:OSM Nominatim Search API
  86: //   13:国土地理院ジオコーディングAPI
  87: define('GEOSERVICE', 1);
  88: 
  89: // 逆ジオコーディングサービスの選択
  90: //    0:Google
  91: //    1:Yahoo!JAPAN
  92: //   11:HeartRails Geo API
  93: //   21:簡易ジオコーディングサービス
  94: define('REVGEOSERVICE', 1);
  95: 
  96: // マップ・グラフの表示サイズ(単位:ピクセル;デフォルト値)
  97: define('DEF_WIDTH',  800);
  98: define('DEF_HEIGHT', 400);
  99: // マップID
 100: define('MAPID', 'map_id');
 101: // 初期値
 102: define('DEF_LATITUDE',  35.4658);       // 緯度
 103: define('DEF_LONGITUDE', 139.6223);      // 経度
 104: define('DEF_TYPE',      'roadmap');     // マップタイプ
 105: define('DEF_ZOOM',      13);            // ズーム
 106: define('DEF_CATEGORY', 'address');      // カテゴリ
 107: 
 108: // マップ中心マーカーのURL;表示しなくなければNULLにする
 109: define('CENTER_MARKER', 'https://www.google.com/mapfiles/arrow.png');
 110: 
 111: // 検索キーの最小文字長
 112: define('QUERY_MIN_LEN', 3);
 113: 
 114: // 検索キーの最大文字長
 115: define('QUERY_MAX_LEN', 99);
 116: 
 117: // OpenWeather API呼び出し回数チェックを有効にする【変更不可】
 118: define('FLAG_OPENWEATHER_COUNTER', TRUE);
 119: 
 120: // 天気予報アイコンファイルのあるフォルダ
 121: define('DIR_WEATHER_ICONS', './weatherIcons/');
 122: 
 123: // 表示モードのデフォルト値
 124: // 0:パラメータ選択入力, 1:画像のみ出力, 2:画像をBASE64出力
 125: define('DEF_MODE', 0);
 126: 
 127: // グラフの背景色(デフォルト値)
 128: define('DEF_BGCOLOR', '#FFFFCC');
 129: 
 130: // 棒グラフに表示するデータ(デフォルト値)
 131: // 0:なし, 1:降水量, 2:気温
 132: define('DEF_BAR_MODE', 1);
 133: 
 134: // 棒グラフの選択肢
 135: // [モード] => array(ラベル, ラベル(単位無し), グラフの色)
 136: $BarList = array(
 137: 0 => array('なし',        'なし',   '#FFFFFF'),
 138: 1 => array('降水量 (mm)', '降水量', '#00CCFF'),
 139: 2 => array('気温 (℃)',   '気温',   '#CC99FF'),
 140: 3 => array('風速 (m/s)',  '風速',   '#00FF66'),
 141: );
 142: 
 143: // 各種定数(END) ===============================================================

各種定数については、とくに記載のないかぎり、自由に変更していただいて構わない。

定数 [DEF_MODE;blue] の使い方は、地図から場所を選んで表示する画面を表示するときは 0 を、緯度・経度をコマンドライン(またはURL)パラメータとして指定し、画像のみを出力したいときは 1 を、その画像をBASE64エンコードした文字列で取得したいときには 2 を指定する。

解説:OpenWeather:Current weather data

OpenWeather:Current weather data」は、要求パラメータは GET 渡しで、現時刻から5日籠まで3時間毎の予報データを応答結果として、XMLや JSON で返すという REST API である。今回使う入力パラメータと応答結果のデータ構造を以下に示す。得られる緯度・経度は世界測地系(wgs84)であることに留意されたい。
クラウドAPI
URL
https://api.openweathermap.org/data/2.5/forecast
入力パラメータ
フィールド名 要否 内  容
appid 必須 OpenWeather APIキー
lat 必須 予報を求めたい地点の緯度(世界測地系;10進小数)
lon 必須 予報を求めたい地点の経度(世界測地系;10進小数)
mode 省略可能 出力書式 = xml|html|json.省略時は json
lang 省略可能 言語.ISO639-1による.日本語なら ja
応答データ構造(xml) weatherdata location name 都市名 country timezone タイムゾーン:UTCからの秒単位のシフト location 緯度・経度・海抜 credit sun 日の出・日没日時 forecast time symbol var="天気予報ID" precipitation probability="降水量" windDirection deg="風向" windSpeed mps="風速" windGust gust="突風" temperature value="気温(K)" feels_like value="体感温度(K) pressure value="気圧(hPa)" humidity value="湿度(%)" clouds all="雲量(%)" visibility value="視程(m)" time symbol precipitation probability="降水量" windDirection deg="風向" windSpeed mps="風速" windGust gust="突風" temperature value="気温(K)" feels_like value="体感温度(K) pressure value="気圧(hPa)" humidity value="湿度(%)" clouds all="雲量(%)" visibility value="視程(m)"

pressureForecast.php

上述のクラウドAPIを利用するユーザー定義メソッドが currentWeatherOpenWeather である。予報を求めたい地点の緯度、経度を引数として渡し、配列 $items に応答結果が入ってくる。
配列 $items の構造は、$items[年][月][日][時][オブジェクト] で、オブジェクトの添字と値の関係は次の通り。
weather天気(日本語)
iconURL天気アイコン(URL)
temperature気温(℃)
pressure気圧(hPa)
wind風速(m/s)
precipitation降水量(mm)

解説:世界時を日本標準時に変換

pahooWeather.php

1105: /**
1106:  * 世界時を日本標準時に変換する
1107:  * @param   string $utc    世界時
1108:  * @param   string $format 変換書式(省略時は 'Y-m-d H:i:s')
1109:  * @return  string 日本標準時
1110: */
1111: function utc2jst($utc, $format='Y-m-d H:i:s') {
1112:     // UTCとして解釈
1113:     $dt = new DateTime($utc, new DateTimeZone('UTC'));
1114: 
1115:     // 日本標準時へ変換
1116:     $dt->setTimezone(new DateTimeZone('Asia/Tokyo'));
1117: 
1118:     // 好きな形式で出力
1119:     return $dt->format($format);
1120: }

要求パラメータとして lang を指定しても、予報日時に世界時が用いられるため、世界時を日本標準時に変換するユーザー定義メソッド utc2jst を用意した。

ケルビン(K)を摂氏(℃)に変換

pahooWeather.php

1122: /**
1123:  * ケルビン(K)を摂氏(℃)に変換する
1124:  * @param   float $kelvin ケルビン
1125:  * @return  float 摂氏(小数第2位で丸める)
1126: */
1127: function kelvin2celsius($kelvin) {
1128:     return round($kelvin - 273.15, 2);
1129: }

温度に関わる応答データの単位がケルビン(K)であるため、これを摂氏(℃)に変換するユーザー定義メソッド kelvin2celsius を用意した。

気圧予報をグラフに描く

pressureForecast.php

 212: /**
 213:  * 気圧予報のグラフを描く
 214:  * @param   array  $item      報告データ
 215:  * @param   int    $modeBar   棒グラフに表示するデータ
 216:  *                  0:なし, 1:降水量, 2:気温
 217:  * @param   int    $width     グラフの高さ(ピクセル)
 218:  * @param   int    $height    グラフの幅(ピクセル)
 219:  * @param   string $bgcolor   グラフの背景色
 220:  * @param   string $address   住所(省略可能)
 221:  * @return  object graphオブジェクト
 222: */
 223: function drawGraph($items, $modeBar, $width, $height, $bgcolor, $address='') {
 224:     global $BarList;
 225: 
 226:     // プロット・データ生成
 227:     $labels    = [];    // X軸ラベル
 228:     $pressure  = [];    // 折れ線グラフ(気圧)
 229:     $dataBar   = [];    // 棒グラフ(Y軸の2軸目)
 230:     $iconsX    = [];
 231:     $iconsY    = [];
 232: 
 233:     ksort($items);
 234:     $m0 = $d0 = -1;
 235:     foreach ($items as $y => $months) {
 236:         ksort($months);
 237:         foreach ($months as $m => $days) {
 238:             ksort($days);
 239:             foreach ($days as $d => $hours) {
 240:                 ksort($hours);
 241:                 foreach ($hours as $h => $obj) {
 242:                     // X軸ラベル
 243:                     $str = '';
 244:                     if ((int)$h % 6 === 0) {
 245:                         $str .sprintf('%d', $h);
 246:                     }
 247:                     if ($m !== $m0) {
 248:                         $str = $str . sprintf("\n%d/%d", $m, $d);
 249:                         $m0 = $m;
 250:                         $d0 = $d;
 251:                     } else if ($d !== $d0) {
 252:                         $str = $str . sprintf("\n%d/%d", $m, $d);
 253:                         $d0 = $d;
 254:                     }
 255:                     $labels[] = $str;
 256:                     // データ
 257:                     $pressure[] = (float)$obj['pressure'];
 258:                     switch ($modeBar) {
 259:                         case 1:
 260:                             $dataBar[]  = (float)$obj['precipitation'];
 261:                             break;
 262:                         case 2:
 263:                             $dataBar[]  = (float)$obj['temperature'];
 264:                             break;
 265:                         case 3:
 266:                             $dataBar[]  = (float)$obj['wind'];
 267:                             break;
 268:                     }
 269:                     // 天気予報アイコン
 270:                     $iconFiles[] = DIR_WEATHER_ICONS . $obj['icon'];
 271:                 }
 272:             }
 273:         }
 274:     }
 275: 
 276:     // グラフ描画の準備
 277:     $graph = new Graph($width, $height);
 278:     $graph->SetScale('textlin');
 279:         $graph->SetY2Scale("lin");
 280: 
 281:     // 背景色の指定
 282:     $graph->SetBackgroundGradient($bgcolor, $bgcolor, GRAD_HOR, BGRAD_MARGIN);
 283: 
 284:     // 棒グラフを生成
 285:     if ($modeBar > 0) {
 286:         $bar = new BarPlot($dataBar);
 287:         $graph->AddY2($bar);    // Y2軸に対応
 288:                                 // ★色指定などはAddの後に記述すること
 289:         $bar->SetFillColor($BarList[$modeBar][2]);  // 塗りつぶし色
 290:         $bar->SetColor($BarList[$modeBar][2]);      // 枠の色
 291:         $bar->SetWidth(0.8);                        // 棒グラフの幅
 292:     }
 293: 
 294:     // 折れ線グラフを生成
 295:     $graph->img->SetAntiAliasing(FALSE);    // アンチエイリアスOFF(太い折れ線)
 296:     $line = new LinePlot($pressure);
 297:     $graph->Add($line);         // Y軸に対応
 298:                                 // ★色指定などはAddの後に記述すること
 299:     $line->SetColor('red');     // 折れ線蔵の負色
 300:     $line->SetWeight(3);        // 折れ線グラフの太さ
 301:     $line->SetLegend('気圧');
 302: 
 303:     // Y軸
 304:     $graph->yaxis->SetColor('black');
 305:     $graph->yaxis->title->SetFont(FF_PGOTHIC);
 306:     $graph->yaxis->SetTitleMargin(40);
 307:     $graph->yaxis->title->Set('気圧 (hPa)');
 308:     if ($modeBar > 0) {
 309:         $graph->y2axis->SetColor('black');
 310:         $graph->y2axis->title->SetFont(FF_PGOTHIC);
 311:         $graph->y2axis->SetTitleMargin(50);
 312:         $graph->y2axis->title->Set($BarList[$modeBar][0]);
 313:         $bar->SetLegend($BarList[$modeBar][1]);
 314:     }
 315: 
 316:     // X軸
 317:     $graph->xaxis->SetTickLabels($labels);
 318:     $graph->xaxis->SetColor('black');
 319:     $graph->xaxis->title->SetFont(FF_PGOTHIC);
 320:     $graph->xaxis->SetTitleMargin(25);
 321:     $graph->xaxis->title->Set('時刻|月日');
 322:     // 毎日0時に縦線を引く
 323:     foreach($labels as $key=>$label) {
 324:         if (preg_match('/^0/i', $label> 0) {
 325:             $vline = new PlotLine(VERTICAL, $key);
 326:             $vline->SetColor('gray@0.5');
 327:             $graph->Add($vline);
 328:         }
 329:     }
 330: 
 331:     // 凡例
 332:     $graph->legend->SetColor('black');
 333:     $graph->legend->SetFont(FF_PGOTHIC);                    // フォント
 334:     $graph->legend->SetColumns(1);                          // 表示列数
 335:     $graph->legend->SetPos(0.01, 0.1, 'right', 'top');      // 位置
 336: 
 337:     // フッタ
 338:     $graph->footer->right->SetFont(FF_PGOTHIC, FS_NORMAL, 10);
 339:     $graph->footer->right->Set('produced by OpenWeather and JpGraph');
 340:     $graph->footer->right->SetColor('blue');
 341:     $graph->img->SetMargin(60, 120, 80, 70);
 342: 
 343:     // タイトル
 344:     $title = '気圧予報';
 345:     if ($address !== '') {
 346:         $title ."({$address})";
 347:     }
 348:     $graph->title->Set($title);
 349:     $graph->title->SetFont(FF_PGOTHIC, FS_NORMAL, 14);
 350:     $graph->title->SetColor('blue');
 351: 
 352:     // 天気予報アイコン
 353:     foreach ($iconFiles as $i => $iconfile) {
 354:     if ($iconfile == '')    continue;
 355:     // 0時・12時に表示
 356:     if ($i % 4 == 0) {
 357:         $icon = new IconPlot($iconfile, 60 + $i * ($width - 60 - 120) / 40, 30);
 358:         $graph->Add($icon);
 359:     }
 360: }
 361: 
 362:     return $graph;
 363: }

気圧予報をグラフに描くユーザー定義関数は [#drawGraphtitle=drawGraph] で、流れとしては「感染症報告数の推移のグラフを作る」と同じである。
違いは、
  • 折れ線グラフが1つ(気圧予報)
  • 2番目の軸(Y2軸)として棒グラフを描く
の2つである。

前述の通り、気圧以外に、もう1つ予報データを棒グラフとして描くことができる。殿データを棒グラフにするかは引数 $modeBar の値によって決まる。値が 0 の時は棒グラフを描かない。

X軸のラベルは、6時間毎に描き、毎日0時に月日を付記するようにした。
また、グラフの上部に IconPlot クラスを使って天気予報アイコンを並べるようにした。こちらは12時間おきにアイコンを表示する。グラフの左右のマージンが異なるので、アイコンの配置座標の計算がやや複雑になっている。

メイン・プログラム

pressureForecast.php

 502: // メイン・プログラム =======================================================
 503: 
 504: // インスタンスを生成する.
 505: $pwt = new pahooWeather();
 506: $pgc = new pahooGeoCode();
 507: 
 508: // 各種パラメータを代入する.
 509: $items = array();
 510: $error = $errmsg = $address = '';
 511: // 表示モード
 512: $mode = getValidNumber('mode', $errmsg, DEF_MODE, TRUE, 0, 2);
 513: if ($errmsg !== '') {
 514:     $error .'<br>表示モードの指定間違いです:' . $errmsg;
 515:     $errmsg = '';
 516: }
 517: // 検索キー
 518: $query    = getValidString('query', $errmsg, '', QUERY_MIN_LEN, QUERY_MAX_LEN);
 519: if ($errmsg !'') {
 520:     $error .'<br>検索キーの長さが ' . $errmsg;
 521:     $errmsg = '';
 522: }
 523: // 緯度
 524: $latitude = getValidNumber('latitude', $errmsg, DEF_LATITUDE, FALSE, -90.0, +90.0);
 525: if ($errmsg !== '') {
 526:     $error .'<br>緯度の指定間違いです:' . $errmsg;
 527:     $errmsg = '';
 528: }
 529: // 経度
 530: $longitude = getValidNumber('longitude', $errmsg, DEF_LONGITUDE, FALSE, -180.0, +180.0);
 531: if ($errmsg !== '') {
 532:     $error .'<br>経度の指定間違いです:' . $errmsg;
 533:     $errmsg = '';
 534: }
 535: // マップ拡大率
 536: $zoom = getValidNumber('zoom', $errmsg, DEF_ZOOM, TRUE, 0, 19);
 537: if ($errmsg !== '') {
 538:     $error .'<br>マップ拡大率の指定間違いです:' . $errmsg;
 539:     $errmsg = '';
 540: }
 541: // マップ・タイプ
 542: $type = (string)getParam('type', FALSE, DEF_TYPE);
 543: // カテゴリ
 544: $category  = (string)getParam('category',    FALSE, DEF_CATEGORY);
 545: $pgc->setYOLP_GeoSelectCategory($category);
 546: // 地図やグラフの横サイズ
 547: $width = getValidNumber('width', $errmsg, DEF_WIDTH, TRUE, 100, 9999);
 548: if ($errmsg !== '') {
 549:     $error .'<br>画面の横サイズの指定間違いです:' . $errmsg;
 550:     $errmsg = '';
 551: }
 552: // 地図やグラフの縦サイズ
 553: $height = getValidNumber('height', $errmsg, DEF_HEIGHT, TRUE, 100, 9999);
 554: if ($errmsg !== '') {
 555:     $error .'<br>画面の横サイズの指定間違いです:' . $errmsg;
 556:     $errmsg = '';
 557: }
 558: // 棒グラフに表示するデータ
 559: $barMode = getValidNumber('barMode', $errmsg, DEF_BAR_MODE, TRUE, min(array_keys($BarList)), max(array_keys($BarList)));
 560: if ($errmsg !== '') {
 561:     $error .'<br>画面の横サイズの指定間違いです:' . $errmsg;
 562:     $errmsg = '';
 563: }
 564: 
 565: // 検索キーをクリアする.
 566: if (isButton('clear')) {
 567:     $mode  = 0;
 568:     $query = '';
 569:     $longitude = DEF_LONGITUDE;
 570:     $latitude  = DEF_LATITUDE;
 571:     $zoom      = DEF_ZOOM;
 572:     $type      = DEF_TYPE;
 573:     $category  = DEF_CATEGORY;
 574:     $width     = DEF_WIDTH;
 575:     $height    = DEF_HEIGHT;
 576:     $barMode   = DEF_BAR_MODE;
 577: 
 578: // 緯度・経度を取得する.
 579: else if (($error === ''&& !isButton('map'&& ($query !'')) {
 580:     list($n, $url) = $pgc->searchPoint3($query, GEOSERVICE, $category);
 581:     // エラーがなければ最初の住所を対象にする
 582:     if (! $pgc->iserror()) {
 583:         list($latitude, $longitude, $address) = $pgc->getPoint(1);
 584:     } else {
 585:         $errmsg = $pgc->geterror();
 586:     }
 587: 
 588: // 住所を取得する.
 589: else if (($errmsg === ''&& isButton('map')) {
 590:     $query = $address = (($arr = $pgc->getAddress3($latitude, $longitude, REVGEOSERVICE)) == FALSE? '' : $arr['address'];
 591: }
 592: 
 593: // マップ描画スクリプトを生成する.
 594: $jsmap = $pgc->drawJSMap(MAPID, $latitude, $longitude, $type, $zoom, NULL, NULL, MAPSERVICE, NULL, NULL, NULL, NULL, CENTER_MARKER);
 595: 
 596: // OpenWeather API呼び出し回数の上限を超えていないかどうか検査する.
 597: if (FLAG_OPENWEATHER_COUNTER) {
 598:     $res = $pwt->addOpenWeatherCounter();
 599:     if ($res === FALSE) {
 600:         $error = $pwt->geterror();
 601:     }
 602: }
 603: 
 604: if ($error === '') {
 605:     // 予報データを取得する.
 606:     $pwt->currentWeatherOpenWeather($latitude, $longitude, $items);
 607: 
 608:     // グラフを生成する.
 609:     $graph = drawGraph($items, $barMode, $width, $height, DEF_BGCOLOR, $address);
 610:     $im = $graph->Stroke(_IMG_HANDLER);
 611: 
 612:     // 画像データのみを出力する.
 613:     if ($mode == 1) {
 614:         header('Content-type: image/webp');
 615:         imagewebp($im, NULL, 75);               // WebP出力
 616:         // PHP8.5:非推奨関数
 617:         if (PHP_VERSION_ID < 80500) {
 618:             imagedestroy($im);                  // 後処理
 619:         }
 620:         exit(1);
 621:     // 画像データをBASE64エンコーディングする.
 622:     } else {
 623:         ob_start();
 624:         imagewebp($im, NULL, 75);               // WebP出力
 625:         // PHP8.5:非推奨関数
 626:         if (PHP_VERSION_ID < 80500) {
 627:             imagedestroy($im);                  // 後処理
 628:         }
 629:         $ImageBase64 = base64_encode(ob_get_clean());
 630:     }
 631: }
 632: 
 633: // 場所情報を配列へ格納する.
 634: $spot['query']     = $query;
 635: $spot['longitude'] = $longitude;
 636: $spot['latitude']  = $latitude;
 637: $spot['address']   = $address;
 638: $spot['zoom']      = $zoom;
 639: $spot['type']      = $type;
 640: $spot['category']  = $category;
 641: 
 642: // 表示用HTMLを生成する.
 643: $HtmlBody = makeCommonBody($mode, $height, $width, $jsmap, $spot, $barMode, $ImageBase64, $errmsg, $pgc, $pwt);
 644: 
 645: // 画面に表示する.
 646: echo $HtmlHeader;
 647: echo $HtmlBody;
 648: echo $HtmlFooter;
 649: 
 650: // インスタンスを解放する.
 651: $pgc = NULL;
 652: $pwt = NULL;
 653: 
 654: /*
 655: ** バージョンアップ履歴 ===================================================
 656:  *
 657:  * @version 1.0.1  2026/03/10 Yahoo!ジオコーディングが利用できない不具合を修正
 658:  * @version 1.0.0  2026/03/07 初版
 659: */

メイン・プログラムは、冒頭の「#flow:title=サンプル・プログラムの流れ]」をそのままコーディングしている。
前半部分はパラメータの取得とバリデーションに費やしている。

参考サイト

(この項おわり)
header