PHPで指定河川の洪水予報を表示する

(1/1)
これまで国土交通省「川の防災情報」を参照し、河川の水位が氾濫注意水位以上の地点をマッピングするプログラムを紹介してきたが、サイト・リニューアルに伴い利用できなくなったため、PHPを使って気象庁防災情報XMLから指定河川の洪水予報をマッピングするPHPプログラムに作り替えた。
表示マップの種類を変えたり、マップを含めてツイートすることができる。

(2023年9月20日)js_html2image()--Leaflet用html2image()発火プロセス見直し
(2022年10月8日)予報がないときの処理追加

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

PHPで指定河川の洪水予報を表示する
Googleマップ

目次

サンプル・プログラム

圧縮ファイルの内容
jmaRiverFloodForecast.phpサンプル・プログラム本体。
pahooGeoCode.php住所・緯度・経度に関わるクラス pahooGeoCode。
使い方は「PHPで住所・ランドマークから最寄り駅を求める」などを参照。include_path が通ったディレクトリに配置すること。
pahooCache.phpキャッシュ処理に関わるクラス pahooCache。
キャッシュ処理に関わるクラスの使い方は「PHPで天気予報を求める」を参照。include_path が通ったディレクトリに配置すること。
pahooTwitterAPI.phpTwitter APIを利用するクラス pahooTwitterAPI。
使い方は「PHPでTwitterに投稿(ツイート)する」などを参照。include_path が通ったディレクトリに配置すること。
jmaRiverFloodForecast.php 更新履歴
バージョン 更新日 内容
1.2.3 2023/09/20 js_html2image()--Leaflet用html2image()発火プロセス見直し
1.22 2022/10/08 getRiverFloodForecast() - 予報がないときの処理追加
1.21 2022/08/04 info2points() - areasが無いデータをスキップ
1.2 2022/07/17 最大プロット数をMAX_MARKERSに定義
1.1 2022/07/09 指定河川洪水予報が無いときのチェックロジック改良
pahooGeoCode.php 更新履歴
バージョン 更新日 内容
6.3.1 2023/07/09 bug-fix
6.3.0 2023/07/02 getPointsGSI()追加
6.2.0 2023/07/02 ip2address()追加
6.1.0 2022/12/30 ip2address()追加
6.0.4 2022/12/13 PHP8.2対応
pahooCache.php 更新履歴
バージョン 更新日 内容
1.1.1 2023/02/11 コメント追記
1.1 2021/04/08 simplexml_load()メソッド追加
1.0 2021/04/02 初版
pahooTwitterAPI.php 更新履歴
バージョン 更新日 内容
5.2.0 2023/07/17 oembed() v2対応
5.1.0 2023/07/16 extractMediaURL() -- file:///形式に対応
5.0.0 2023/07/02 メソッドをTwitter API v2へ移行;v1.1は別名or廃止
4.9.0 2023/04/15 tweet3() 追加
4.8.0 2023/01/28 tweet2(),twitter_strcut2(),extractMediaURL()追加

気象庁防災情報XMLフォーマット

気象庁防災情報XMLフォーマットは、気象や地震、火山に関する情報を随時流している。
まず、下表の6つの Atomフィードにアクセスし、必要なXML情報のURLを求める。
フィードの構造(xml) feed title タイトル subtitle サブタイトル updated 配信日時 id ID rights 著作権表記 entry title XML情報タイトル(1) id XML情報のURL(1) updated 更新日時(1) author name 作者(1) content 内容説明(1) entry title XML情報タイトル(2) id XML情報のURL(2) updated 更新日時(2) author name 作者(2) content 内容説明(2)
XML情報のURLの命名規則は以下の通り。
https://www.data.jma.go.jp/developer/xml/data/yyyymmddhhmmss_番号_電文コード_連番.xml
指定河川の洪水予報に関する情報は、長期フィードの随時の中にある電文コード VXKO に入っている。そこで、フィードから VXKO を含むURLを取り出せば、それが目指す情報XMLとなる。

VXKOの構造

指定河川の洪水予報に関する情報XML VXKO の構造は下記の通りである。
ここから必要な情報を取り出す。
VXKOの構造(xml) Report Control Title 指定河川洪水予報に関する情報 DateTime 作成日時 Status ステータス EditorialOffice 編集者 PublishingOffice 配信者 Head Title 標題 ReportDateTime 発表日時 TargetDateTime 基点日時 EventID 識別情報 InfoType 情報系大雨 Serial 情報番号 InfoKind スキーマの運用種別情報 InfoKindVersion スキーマの運用種別のバージョン情報 Headline Text 見出し Body Warning Item Kind Property Type 主文1 Text 主文1の内容 Kind Property Type 主文2 Text 主文2の内容 Areas Area Name 河川名 Code 河川コード Item Kind Property Type 浸水想定地区 Areas Area Name 観測所名称1 Code 観測所コード1 Prefecture 都道府県名1 PrefectureCode 都道府県コード1 City 市町村名1 CityCode 市町村コード1 Area Name 観測所名称2 Code 観測所コード2 Prefecture 都道府県名2 PrefectureCode 都道府県コード2 City 市町村名2 CityCode 市町村コード2 MeteorologicalInfos MeteorologicalInfo DateTime 予報・観測の基点時刻 Item Kind Property Type 雨量 Text 雨量の予報・観測文

準備:pahooGeoCode クラス

  37: class pahooGeoCode {
  38:     var $items;     //検索結果格納用
  39:     var $error;     //エラー・フラグ
  40:     var $errmsg;    //エラー・メッセージ
  41:     var $hits;      //検索ヒット件数
  42:     var $webapi;    //直前に呼び出したWebAPI URL
  43: 
  44:     //Google Cloud Platform APIキー
  45:     //https://cloud.google.com/maps-platform/
  46:     //※Google Maps APIを利用しないのなら登録不要
  47:     var $GOOGLE_API_KEY_1 = '**************************';   //HTTPリファラ用
  48:     var $GOOGLE_API_KEY_2 = '**************************';   //IP制限用
  49: 
  50:     //Yahoo! JAPAN Webサービス アプリケーションID
  51:     //https://e.developer.yahoo.co.jp/register
  52:     //※Yahoo! JAPAN Webサービスを利用しないのなら登録不要
  53:     var $YAHOO_APPLICATION_ID = '*****************************';

地図サービスを利用するために、クラスファイル "pahooGeoCode.php" を使用する。組み込み関数  require_once  を使って読めるディレクトリに配置する。ディレクトリは、設定ファイル php.ini に記述されているオプション設定 include_path に設定しておく。
クラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。

地図としてGoogleマップを利用するのであれば、Google Cloud Platform APIキー が必要で、その入手方法は「Google Cloud Platform - WebAPIの登録方法」を参照されたい。

準備:地図サービスの選択

  40: //地図描画サービスの選択
  41: //    0:Google
  42: //    2:地理院地図・OSM
  43: define('MAPSERVICE', 2);
  44: 
  45: //住所検索サービスの選択
  46: //    0:Google
  47: //    1:Yahoo!JAPAN
  48: //   11:HeartRails Geo API
  49: //   12:OSM Nominatim Search API
  50: define('GEOSERVICE', 1);

表示する地図は、Googleマップ地理院地図・オープンストリートマップ(OSM)から選べる。あらかじめ、定数 MAPSERVICE に値を設定すること。
観測所の都道府県・市町村名からマッピング位置を特定するための住所検索サービスは、GoogleYahoo!JAPANHeartRails Geo APIOSM Nominatim Search API から選べる。あらかじめ、定数 GEOSERVICE に値を設定すること。
PHPで直近の地震情報を表示する
オープンストリートマップ+色別標高図+活断層図

準備:キャッシュ・システム

  67: //キャッシュ保持時間(分) 0:キャッシュしない
  68: //気象庁へのアクセス負荷軽減のため,適切な時間を設定してください.
  69: define('LIFE_CACHE_FEED',     5);       //高頻度 - 随時フィードに対して
  70: define('LIFE_CACHE_FEED_L', 120);       //長期 - 随時フィードに対して
  71: define('LIFE_CACHE_DATA',   720);       //指定河川洪水予報情報に対して
  72: 
  73: //キャッシュ・ディレクトリ
  74: //書き込み可能で,外部からアクセスされないディレクトリを指定してください.
  75: //天気予報系のプログラムとは別のディレクトリを指定してください.
  76: define('DIR_CACHE_FEED',   './pcache1/');
  77: define('DIR_CACHE_FEED_L', './pcache2/');
  78: define('DIR_CACHE_DATA',   './pcache3/');

気象庁サイトへ負荷をかけないよう、キャッシュ・クラス pahooCache を導入した。使用方法については、「PHPで天気予報を求める - キャッシュ・システム」を参照いただきたい。
キャッシュ保持時間、キャッシュ・ディレクトリともに、自サイトの環境に応じて変更してほしい。天気予報系プログラムと別のキャッシュ・ディレクトリにした方が、お互いのキャッシュ保持時間の干渉を受けなくなる。
配布ファイルは、新しい地震情報が入ってくることを考え、フィードの方を短く、指定河川洪水予報情報の方は長くキャッシュ保持時間を設定してある。

準備:各種定数

  52: //マップの表示サイズ(単位:ピクセル)
  53: define('MAP_WIDTH',  640);
  54: define('MAP_HEIGHT', 480);
  55: //マップID
  56: define('MAPID', 'map_id');
  57: //初期値
  58: define('DEF_LATITUDE',  38.82);             //緯度
  59: define('DEF_LONGITUDE', 138.28);            //経度
  60: define('DEF_ZOOM',      5);                 //ズーム
  61: define('DEF_TYPE',     'ROADMAP');          //マップタイプ
  62: define('DEF_OVERLAYS', 'GSIELEV,GSIFAULT'); //オーバーレイ(Leaflet使用時のみ)
  63: define('INFO_WIDTH', (MAP_WIDTH * 0.75));   //情報ウィンドウの最大幅
  64: define('INFO_OFFSET_X',   0);           //情報ウィンドウのオフセット位置(X)
  65: define('INFO_OFFSET_Y', -25);           //情報ウィンドウのオフセット位置(Y)
  66: 
  67: //キャッシュ保持時間(分) 0:キャッシュしない
  68: //気象庁へのアクセス負荷軽減のため,適切な時間を設定してください.
  69: define('LIFE_CACHE_FEED',     5);       //高頻度 - 随時フィードに対して
  70: define('LIFE_CACHE_FEED_L', 120);       //長期 - 随時フィードに対して
  71: define('LIFE_CACHE_DATA',   720);       //指定河川洪水予報情報に対して
  72: 
  73: //キャッシュ・ディレクトリ
  74: //書き込み可能で,外部からアクセスされないディレクトリを指定してください.
  75: //天気予報系のプログラムとは別のディレクトリを指定してください.
  76: define('DIR_CACHE_FEED',   './pcache1/');
  77: define('DIR_CACHE_FEED_L', './pcache2/');
  78: define('DIR_CACHE_DATA',   './pcache3/');
  79: 
  80: //これより古い情報は無視する(単位:時間)
  81: define('INTERVAL', 24);
  82: 
  83: //最大プロット数
  84: define('MAX_MARKERS', 999);
  85: 
  86: //警戒レベルのアイコン
  87: define('ICON_CAUSION', 'https://maps.google.com/mapfiles/ms/micons/red-dot.png');
  88: //予報アイコン
  89: define('ICON_FORECAST', 'https://maps.google.com/mapfiles/ms/micons/yellow-dot.png');
  90: 
  91: //SQLite DBファイル名:各自の環境に合わせて変更すること
  92: define('DBFILE', './riverFloodArea.sqlite3');
  93: 
  94: //SQLite テーブル名:浸水想定地区
  95: define('TABLE_AREA', 'area');
  96: 
  97: //実行するSQL:浸水想定地区【変更不可】
  98: define('PRE_SELECT', 'SELECT * FROM ' . TABLE_AREA . ' WHERE id=:id');
  99: define('PRE_INSERT', 'INSERT INTO ' . TABLE_AREA . ' (id, area, latitude, longitude, premiere, latest) VALUES (:id, :area, :latitude, :longitude, :premiere, :latest)');
 100: define('PRE_UPDATE', 'UPDATE ' . TABLE_AREA . ' set area=:area, latitude=:latitude, longitude=:longitude, latest=:latest WHERE id=:id');
 101: 
 102: //気象庁防災情報XML:高頻度フィード - 随時【変更不可】
 103: define('FEED', 'https://www.data.jma.go.jp/developer/xml/feed/extra.xml');
 104: 
 105: //気象庁防災情報XML:長期フィード - 随時【変更不可】
 106: define('FEED_L', 'https://www.data.jma.go.jp/developer/xml/feed/extra_l.xml');
 107: 
 108: //住所・緯度・経度に関わるクラス:include_pathが通ったディレクトリに配置
 109: require_once('pahooGeoCode.php');
 110: 
 111: //キャッシュ処理に関わるクラス:include_pathが通ったディレクトリに配置
 112: require_once('pahooCache.php');
 113: 
 114: //Twitterクラス:include_pathが通ったディレクトリに配置
 115: if (TWITTER) {
 116:     require_once('pahooTwitterAPI.php');
 117: }

表示に関わる各種パラメータは定数を defineしている。【変更不可】の記載のないものは、適宜変更してかまわない。

解説:気象庁防災情報XMLから指定河川洪水予報に関する情報URLを取得

 449: /**
 450:  * 気象庁防災情報XMLから指定河川洪水予報に関する情報URLを取得
 451:  * @param   array  $urls    URL格納配列
 452:  * @param   string $errmsg  エラーメッセージ格納用
 453:  * @return  bool TRUE:取得成功/FALSE:取得失敗
 454: */
 455: function jmaGetRiverFloodForecastURLs(&$urls, &$errmsg) {
 456:     //URLパターン
 457:     $vxko = '/https?\:\/\/www\.data\.jma\.go\.jp\/developer\/xml\/data\/([0-9\_]+)VXKO[0-9]+\_[0-9]+\.xml/ui';
 458: 
 459:     //随時フィードの解析
 460:     $cnt = 0;
 461:     $pcc = new pahooCache(LIFE_CACHE_FEED, DIR_CACHE_FEED);
 462:     $xml = $pcc->simplexml_load(FEED);
 463:     //レスポンス・チェック
 464:     if ($pcc->iserror() || !isset($xml->entry)) {
 465:         $errmsg = '気象庁防災情報XMLにアクセスできません';
 466:         return FALSE;
 467:     }
 468:     foreach ($xml->entry as $node) {
 469:         //URLを取得
 470:         if (preg_match($vxko, $node->id, $arr> 0) {
 471:             $urls[$cnt] = $arr[0];
 472:             $cnt++;
 473:         }
 474:     }
 475:     $pcc = NULL;
 476: 
 477:     //長期フィードの解析
 478:     $pcc = new pahooCache(LIFE_CACHE_FEED_L, DIR_CACHE_FEED_L);
 479:     $xml = $pcc->simplexml_load(FEED_L);
 480:     //レスポンス・チェック
 481:     if ($pcc->iserror() || !isset($xml->entry)) {
 482:         $errmsg = '気象庁防災情報XMLにアクセスできません';
 483:         return FALSE;
 484:     }
 485:     foreach ($xml->entry as $node) {
 486:         //URLを取得
 487:         if (preg_match($vxko, $node->id, $arr> 0) {
 488:             if (array_search($arr[0], $urls) === FALSE) {
 489:                 $urls[$cnt] = $arr[0];
 490:                 $cnt++;
 491:             }
 492:         }
 493:     }
 494:     $pcc = NULL;
 495: 
 496:     //エラー・チェック
 497: //  if ($cnt == 0) {
 498: //      $errmsg = '指定河川洪水予報はありません';
 499: //      return FALSE;
 500: //  }
 501: 
 502:     //URLを日時の新しい順にソート
 503:     if (count($urls> 0)   rsort($urls);
 504: 
 505:     return TRUE;
 506: }

前述のフィードから、指定河川洪水予報に関する情報URLを取得するユーザー関数が jmaGetRiverFloodForecastURLs である。
VXKO を含むURLを配列 $urls に格納していき、最後に配列 $urls を大きい順にソートすることで、日付の新しい順にソートしたことになる。

解説:指定河川洪水予報情報の取り出し

指定河川洪水予報情報の取り出し
指定河川洪水予報情報に関する情報XML VXKO から、発表日時、主文、洪水想定地区、雨量を取り出し、配列 $items に格納する。

VXKO からは洪水想定地区の緯度・経度が分からないため、pahooGeoCodeクラスのメソッド searchPoint3 を使って緯度・経度を取得する。
このメソッドは、WebAPIを呼び出して住所から緯度・経度を取得するものだが、いちいち呼び出すと時間がかかる(GoogleAPIは費用もかかる)ので、一度検索したデータはデータベース SQLite に格納しておき、二度目からはDBのデータを取り出すようにした。

 508: /**
 509:  * 指定河川洪水予報情報を取得(気象庁防災情報XMLから)
 510:  * @param   object $pgc     pahooGeoCodeオブジェクト
 511:  * @param   array  $items   指定河川洪水予報を格納する配列
 512:  * @param   string $urls    情報XMLのURLを格納する配列
 513:  * @param   string $errmsg  エラーメッセージ格納用
 514:  * @return  bool TRUE:取得成功/FALSE:失敗
 515: */
 516: function getRiverFloodForecast($pgc, &$items, &$urls, &$errmsg) {
 517:     //マッチングパターン
 518:     $pat1 = '/([0-9]+)\-([0-9]+)\-([0-9]+)T([0-9]+)\:([0-9]+)/ui';      //年月日時分
 519: 
 520:     //オブジェクト生成
 521:     $pcc = new pahooCache(LIFE_CACHE_DATA, DIR_CACHE_DATA);
 522:     $pgc = new pahooGeoCode();
 523: 
 524:     //DBオープン
 525:     $pdo = new PDO('sqlite:' . DBFILE);
 526: 
 527:     //指定河川洪水予報取に関する情報URLを取得
 528:     $urls = array('');
 529:     jmaGetRiverFloodForecastURLs($urls, $errmsg);
 530:     if ($errmsg !'')      return FALSE;
 531:     if (count($urls) == 0)  return TRUE;
 532: 
 533:     $count = 1;
 534:     foreach ($urls as $key=>$vxko) {
 535:         //指定河川洪水予報の取得
 536:         $xml = $pcc->simplexml_load($vxko);
 537:         if ($xml == FALSE)  continue;           //ver.1.22
 538: 
 539:         //レスポンス・チェック
 540:         if ($pcc->iserror() || !isset($xml->Body->Warning->Item)) {
 541:             $errmsg = '気象庁防災情報XMLから指定河川洪水予報を取得できません';
 542:             return FALSE;
 543:         }
 544:         //発表日時
 545:         $dt = (string)$xml->Head->ReportDateTime;
 546:         //古い情報かどうか
 547:         if (time() - strtotime($dt> INTERVAL * 60 * 60) {
 548:             continue;
 549:         }
 550:         $items[$count]['dt'] = $dt;
 551:         preg_match($pat1, $dt, $arr);
 552:         $items[$count]['year']    = (int)$arr[1];
 553:         $items[$count]['month']   = (int)$arr[2];
 554:         $items[$count]['day']     = (int)$arr[3];
 555:         $items[$count]['hour']    = (int)$arr[4];
 556:         $items[$count]['minuite'] = (int)$arr[5];
 557:         //指定河川洪水予報
 558:         $data = array();
 559:         foreach ($xml->Body->Warning->Item as $item) {
 560:             //主文
 561:             if (isset($item->Kind->Property->Type&& ((string)$item->Kind->Property->Type == '主文')) {
 562:                 if (isset($items[$count]['main'])) {
 563:                     $items[$count]['main'."\n" . (string)$item->Kind->Property->Text;
 564:                 } else {
 565:                     $items[$count]['main'] = (string)$item->Kind->Property->Text;
 566:                 }
 567:             //浸水想定地区
 568:             } else if (isset($item->Kind->Property->Type&& ((string)$item->Kind->Property->Type == '浸水想定地区')) {
 569:                 $i = 1;
 570:                 foreach ($item->Areas->Area as $area) {
 571:                     $query = (string)$area->Prefecture . (string)$area->City;
 572:                     $items[$count]['areas'][$i]['area'] = $query;
 573:                     $id = (string)$area->CityCode;
 574:                     //緯度・経度をDBから取得
 575:                     if (getAreaFromDB($pdo, $id, $data)) {
 576:                         $latitude  = $data['latitude'];
 577:                         $longitude = $data['longitude'];
 578:                     } else {
 579:                         list($n, $url) = $pgc->searchPoint3($query, GEOSERVICE, 'address');
 580:                         //エラーがなければ最初の住所を対象にする
 581:                         if (! $pgc->iserror()) {
 582:                             list($latitude, $longitude, $address) = $pgc->getPoint(1);
 583:                             //DB登録
 584:                             $data['area']      = $query;
 585:                             $data['latitude']  = $latitude;
 586:                             $data['longitude'] = $longitude;
 587:                             $res = storeAreaToDB($pdo, $id, $data);
 588:                             if (! $res) {
 589:                                 $errmsg = 'DB書き込みに失敗しました';
 590:                                 return FALSE;
 591:                             }
 592:                         } else {
 593:                             $errmsg = $pgc->geterror();
 594:                             return FALSE;
 595:                         }
 596:                     }
 597:                     $items[$count]['areas'][$i]['latitude']  = $latitude;
 598:                     $items[$count]['areas'][$i]['longitude'] = $longitude;
 599:                     $i++;
 600:                 }
 601:             }
 602:         }
 603:         //雨量情報
 604:         if (isset($xml->Body->MeteorologicalInfos->MeteorologicalInfo->Item)) {
 605:             foreach ($xml->Body->MeteorologicalInfos->MeteorologicalInfo->Item as $item) {
 606:                 if (isset($item->Kind->Property->Type&& ((string)$item->Kind->Property->Type == '雨量')) {
 607:                     if (isset($items[$count]['rainfall'])) {
 608:                         $items[$count]['rainfall'."\n" . (string)$item->Kind->Property->Text;
 609:                     } else {
 610:                         $items[$count]['rainfall'] = (string)$item->Kind->Property->Text;
 611:                     }
 612:                 }
 613:             }
 614:         }
 615:         $count++;
 616:     }
 617: 
 618:     //DBクローズ
 619:     $pdo = NULL;
 620:     //オブジェクト解放
 621:     $pgc = $pcc = NULL;
 622: 
 623:     return TRUE;
 624: }

SQLite のデータベースは、メインプログラムの冒頭でユーザー関数 initDB を呼び出し、データベースファイル DBFILE が存在しなければ新規作成するようにしている。

 266: /**
 267:  * DBの初期化
 268:  * @param   なし
 269:  * @return  bool TRUE/FALSE
 270: */
 271: function initDB() {
 272:     try {
 273:         $pdo = new PDO('sqlite:' . DBFILE);
 274:         $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 275: 
 276:         //テーブル作成:浸水想定地区
 277:         //id:観測所のCityCode, area:都道府県+市町村名
 278:         //latitude:緯度, longitude:経度
 279:         //premiere:登録日時, latest:更新日時
 280:         $pdo->exec('CREATE TABLE IF NOT EXISTS ' . TABLE_AREA . '(
 281:          id        INTEGER PRIMARY KEY AUTOINCREMENT,
 282:             area      TEXT,
 283:             latitude  REAL,
 284:             longitude REAL,
 285:             premiere  TEXT,
 286:             latest    TEXT
 287:         )');
 288:      $res = TRUE;
 289:     } catch (PDOException $e) {
 290:         $res = FALSE;
 291:     }
 292: 
 293:     return $res;
 294: }

解説:指定河川洪水予報情報をマッピング情報に変換

 626: /**
 627:  * 指定河川洪水予報情報をマッピング情報に変換
 628:  * @param   array  $items   指定河川洪水予報情報を格納した配列
 629:  * @param   array  $points  マッピング情報を格納する配列
 630:  * @return  int 変換したマッピング情報の件数
 631: */
 632: function info2points(&$items, &$points) {
 633:     //データがない
 634:     if (count($items) == 0)     return 0;
 635: 
 636:     //変換処理
 637:     $i = $j = 0;
 638:     $cnt = 1;
 639:     foreach ($items as $i=>$item) {
 640:         if ($cnt > MAX_MARKERS)     break;          //最大プロット数
 641:         if (!isset($item['areas']))     continue;   //Ver.1.21修正
 642:         foreach ($item['areas'as $j=>$val) {
 643:             //同じマッピング位置があるかどうか
 644:             $flag = FALSE;
 645:             for ($k = 1$k < $cnt$k++) {
 646:                 if ($val['area'] == $points[$k]['title']) {
 647:                     $flag = TRUE;
 648:                     break;
 649:                 }
 650:             }
 651:             //新規のマッピング情報
 652:             if (! $flag) {
 653:                 //アイコン
 654:                 if (preg_match('/警戒レベル/ui', $items[$i]['main']) > 0) {
 655:                     $points[$cnt]['icon'] = ICON_CAUSION;
 656:                 } else {
 657:                     $points[$cnt]['icon'] = ICON_FORECAST;
 658:                 }
 659:                 //タイトル
 660:                 $points[$cnt]['title'] = $val['area'];
 661:                 //緯度・経度
 662:                 $points[$cnt]['latitude']  = $items[$i]['areas'][$j]['latitude'];
 663:                 $points[$cnt]['longitude'] = $items[$i]['areas'][$j]['longitude'];
 664:                 //情報ウィンドウの内容
 665:                 $points[$cnt]['description'] = 
 666:                     sprintf('%04d年%02d月%02d日 %02d時%02d分 発表<br /><span style="font-weight:bold;">%s</span><br />%s<br />%s',  $items[$i]['year'],
 667:                         $items[$i]['month'],
 668:                         $items[$i]['day'],
 669:                         $items[$i]['hour'],
 670:                         $items[$i]['minuite'],
 671:                         $val['area'],
 672:                         preg_replace('/\n/', '<br />', $items[$i]['main']),
 673:                         preg_replace('/\n/', '<br />', $items[$i]['rainfall']));
 674:                     $cnt++;
 675:             }
 676:         }
 677:     }
 678: 
 679:     return $cnt;
 680: }

getRiverFloodForecast で得た指定河川洪水予報情報を、マッピングしやすいように、洪水想定地区をキーに配列 $points に展開するユーザー関数が info2points である。

解説:地図描画について

マップの描画については、「PHPで住所・ランドマークから最寄り駅を求める」をご覧いただきたい。

解説:オーバーレイ表示(Leaflet選択時のみ)

マップで Leaflet を選択したとき、オーバーレイ地図を表示できるようにした。
詳しくは「PHPで最近の地震情報を表示する」をご覧いただきたい。

解説:ツイート機能

表示した天気図(マップ)を画像として、メッセージと一緒にボタン1つでツイートする機能を追加した。流れは「PHPで最近の地震情報を表示する」で解説したとおりである。

活用例

みんなの知識 ちょっと便利帳」では、「指定河川洪水予報を地図上に表示」で本プログラムを利用し、見やすいページを提供している。ありがとうございます。

参考サイト

(この項おわり)
header