PHPで地図上に円や矩形を描く

(1/1)
ジャスコ釧路店 直進110km」というツイートにインスパイアされ、北海道と他府県の距離感の違いを地図上に描いてみようと思い立った。

Googleマップは、WebAPI機能として円や矩形を描く機能を備えている。また、地理院地図、オープンストリートマップについては、「PHPで住所・ランドマークから最寄り駅を求める」で紹介したJavaScriptライブラリ Leaflet を使うことで同様の処理が可能となる。
そこで、PHPで中心点と対角点または距離を指定し、中心点と対角点は住所などでの検索を可能とし、地図上に円や矩形を描くプログラムを作っていくことにする。

(2025年8月13日)GoogleMaps JavaScript APIの変更に対応した..pahooEnv 導入

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

PHPで地図上に円や矩形を描く
Googleマップ表示

目次

サンプル・プログラム

圧縮ファイルの内容
drawArea.phpサンプル・プログラム本体
.pahooEnvクラウドサービスを利用するためのアカウント情報などを記入する .env ファイル。
使い方は「各種クラウド連携サービス(WebAPI)の登録方法」を参照。include_path が通ったディレクトリに配置すること。
pahooGeoCode.php住所・緯度・経度に関わるクラス pahooGeoCode。
使い方は「PHPで住所・ランドマークから最寄り駅を求める」「PHPで住所・ランドマークから緯度・経度を求める」などを参照。include_path が通ったディレクトリに配置すること。
pahooInputData.phpデータ入力に関わる関数群。
使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。
drawArea.php 更新履歴
バージョン 更新日 内容
1.2.0 2025/08/13 GoogleMaps JavaScript API 仕様変更対応
1.1 2022/04/29 PHP8対応,リファラ・チェック改良
1.0 2019/06/15
pahooGeoCode.php 更新履歴
バージョン 更新日 内容
6.8.0 2025/08/10 アクセスキーなどを ".env" に分離
6.7.1 2025/07/26 jsLine_Gmap() - bug-fix
6.7.0 2025/07/20 drawJSmap,drawGMap -- 引数 $markerLevel 追加
6.6.0 2025/07/19 drawJSmap,drawGMap,drawLeaflet -- マップ中心マーカー表示引数を追加
6.5.0 2025/06/14 GoogleMaps JavaScript APIの変更に対応
pahooInputData.php 更新履歴
バージョン 更新日 内容
2.0.1 2025/08/11 getParam() bug-fix
2.0.0 2025/08/11 pahooLoadEnv() 追加
1.9.0 2025/07/26 getParam() 引数に$trim追加
1.8.1 2025/03/15 validRegexPattern() debug
1.8.0 2024/11/12 validRegexPattern() 追加

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

PHPで地図上に円や矩形を描く
  1. 中心点($center)または対角点($diagonal)が指定されていれば、pahooGeoCode::searchPoint3 メソッドを呼び出し、緯度・経度を求める。
  2. 対角点はないが距離($distance)があれば、pahooGeoCode::getPointDistance メソッドを呼び出し、中心から北西へ指定距離だけ離れた地点の緯度・経度を求め、これを対角点とする。
  3. 対角点があるか、または距離がなければ、pahooGeoCode::rhumbLine メソッドを呼び出し、中心と対角点の間の距離(等角航路距離)を計算する。
  4. 以上の計算が終わったら、中心点の存在する象限に応じて矩形の南西端と北東端を計算する。
  5. 地図描画のために必要な変数を代入し、定数 MAPSERVICE の値に応じ、Googleマップ、Leafletの描画スクリプトを生成する。マップごとに、さらに円描画か矩形描画かを場合分けしている。
  6. 生成したスクリプトを pahooGeoCode::drawJSMap メソッドに渡し、画面上に地図と図形を表示する。

準備: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

  40: class pahooGeoCode {
  41:     public $items;      // 検索結果格納用
  42:     public $error;      // エラー・フラグ
  43:     public $errmsg;     // エラー・メッセージ
  44:     public $hits;       // 検索ヒット件数
  45:     public $webapi// 直前に呼び出したWebAPI URL
  46: 
  47:     // -- 以下のデータは .env ファイルに記述可能
  48:     // Google Cloud Platform APIキー
  49:     // https://cloud.google.com/maps-platform/
  50:     // ※Google Maps APIを利用しないのなら登録不要
  51:     public $GOOGLE_API_KEY_1 = '';      // HTTPリファラ用
  52:     public $GOOGLE_API_KEY_2 = '';      // IP制限用
  53:     public $GOOGLE_MAP_ID    = '';      // GoogleMaps ID
  54: 
  55:     // Yahoo! JAPAN Webサービス アプリケーションID
  56:     // https://e.developer.yahoo.co.jp/register
  57:     // ※Yahoo! JAPAN Webサービスを利用しないのなら登録不要
  58:     public $YAHOO_APPLICATION_ID = '';
  59: 
  60:     // OSM Nominatim Search API利用時に知らせるメールアドレス
  61:     // https://wiki.openstreetmap.org/wiki/JA:Nominatim#.E6.A4.9C.E7.B4.A2
  62:     // ※OSM Nominatim Search APIを利用しないのなら登録不要
  63:     public $NOMINATIM_EMAIL = '';
  64: 
  65:     // IP2Location.io APIキー
  66:     // https://www.ip2location.io/
  67:     // ※IP2Location.ioを利用しないのなら登録不要
  68:     public $IP2LOCATION_API_KEY = '';

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

地図や住所検索として 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でクラスを使ってテキストの読みやすさを調べる」を参照されたい。

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

drawArea.php

  63: // 地図描画サービスの選択
  64: //    0:Google
  65: //    2:地理院地図・OSM
  66: define('MAPSERVICE', 0);
  67: 
  68: // 住所検索サービスの選択
  69: //    0:Google
  70: //    1:Yahoo!JAPAN
  71: //   11:HeartRails Geo API
  72: define('GEOSERVICE', 11);
  73: 
  74: // 逆ジオコーディングサービスの選択
  75: //    0:Google
  76: //    1:Yahoo!JAPAN
  77: //   11:HeartRails Geo API
  78: //   21:簡易ジオコーディングサービス
  79: define('REVGEOSERVICE', 11);

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

準備:カラーピッカー Spectrum

drawArea.php

 111: // jQueryのフルパス
 112: define('JQUERY', 'https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js');
 113: 
 114: // カラーピッカー Spectrum のパス
 115: define('SPECTRUM', 'https://www.pahoo.org/common/js/spectrum/');

図形の境界線および塗りつぶしカラーを選択するために、JavaScriptライブラリ Spectrum を利用する。公式サイトからダウンロードしたら、その場所を定数 SPECTRUM に代入しておくこと。
また、jQuery も利用するので、その場所を定数 JQUERY に代入しておくこと。

drawArea.php

 139: <script src="{$jquery}"></script>
 140: <script src="{$spectrum}spectrum.js"></script>
 141: <script>
 142: $(function() {
 143:     $("#border_color").spectrum({
 144:         showAlpha: false,
 145:         showPalette: true,
 146:         palette: [
 147:             ["#0000FF", "#FF0000", "#FF00FF"],
 148:             ["#00FF00", "#00FFFF", "#FFFF00"]
 149:         ],
 150:         maxSelectionSize: 4,
 151:         preferredFormat: "hex",
 152:         showInput: true
 153:     });
 154:     $("#fill_color").spectrum({
 155:         showAlpha: true,
 156:         showPalette: true,
 157:         palette: [
 158:             ["rgba(0, 0, 255, 0.3)", "rgba(255, 0, 0, 0.3)", "rgba(255, 0, 255, 0.3)"],
 159:             ["rgba(0, 255, 0, 0.3)", "rgba(0, 255, 255, 0.3)", "rgba(255, 255, 0, 0.3)"],
 160:         ],
 161:         maxSelectionSize: 4,
 162:         preferredFormat: "rgb",
 163:         showInput: true
 164:     });
 165: });

Spectrum の表示は、この部分で設定している。境界色パレットには8色カラーを、領域色パレットには8色カラー(透明度0.3)と透明度スライドバーを用意した。自由に変更可能である。

準備:初期値

drawArea.php

  81: // マップの表示サイズ(単位:ピクセル)
  82: define('MAP_WIDTH',  600);
  83: define('MAP_HEIGHT', 600);
  84: // マップID
  85: define('MAPID', 'map_id');
  86: // アイコン(中心)
  87: define('ICON_CENTER', 'https://maps.google.co.jp/mapfiles/ms/icons/red-dot.png');
  88: // アイコン(対角)
  89: define('ICON_DIAGONAL', 'https://labs.google.com/ridefinder/images/mm_20_red.png');
  90: // 初期値
  91: define('DEF_LONGITUDE0',    139.766667);        // 地図中心(経度)
  92: define('DEF_LATITUDE0',     35.681111);         //    (緯度)
  93: define('DEF_CENTER',        '');                // 検索クエリ(center)
  94: define('DEF_DIAGONAL',      '');                //     (diagonal)
  95: define('DEF_CAT_CENTER',    'address');         // 領域中心(カテゴリ)
  96: define('DEF_CAT_DIAGONAL',  'address');         // 領域対角(カテゴリ)
  97: define('DEF_LONGITUDE1',    139.766667);        // 領域中心(経度)
  98: define('DEF_LATITUDE1',     35.681111);         //    (緯度)
  99: define('DEF_LONGITUDE2',    139.700278);        // 領域対角(経度)
 100: define('DEF_LATITUDE2',     35.690833);         //      (緯度)
 101: define('DEF_TYPE',          'roadmap');         // マップタイプ
 102: define('DEF_ZOOM',          12);                // ズーム
 103: define('DEF_FIGURE',        'circle');          // 図形タイプ
 104: define('DEF_BORDER_COLOR',  '#FF0000');         // 境界色
 105: define('DEF_FILL_COLOR',    '#FF0000');         // 領域色
 106: define('DEF_OPACITY',       0.3);               // 透明度

これらの初期値は、プログラム初回起動時、またはリセット・ボタン押下時に採用される値である。自由に変更できる。

Googleマップでの図形描画

drawArea.php

 306: /**
 307:  * マーカー設定、フィット機能:Googleマップ用スクリプト
 308:  * @param   float $latitude, $longitude 経路の中央点座標(緯度・経度)
 309:  * @param   bool $drag TRUE:ドラッグで再描画する/FALSE:しない(デフォルト)
 310:  * @return  string JavaScript
 311: */
 312: function jsDragMarker_Gmap($latitude, $longitude, $drag=FALSE) {
 313:     $submit = $drag ? 'document.myform.submit();' : '';
 314: 
 315:     $js =<<< EOT
 316:     //イベント設定
 317:     document.getElementById('fit').addEventListener('click', fitting, false);
 318: 
 319:     // マーカー設定
 320:     marker_001.setDraggable(true);
 321:     google.maps.event.addListener(marker_001, 'dragend', function() {
 322:         let latlng = marker_001.getPosition();
 323:         document.getElementById('longitude1').value = latlng.lng();
 324:         document.getElementById('latitude1').value  = latlng.lat();
 325:         document.getElementById('center').value = '';
 326:         document.getElementById('distance').value = '';
 327:         {$submit}
 328:     });
 329: 
 330:     marker_002.setDraggable(true);
 331:     google.maps.event.addListener(marker_002, 'dragend', function() {
 332:         let latlng = marker_002.getPosition();
 333:         document.getElementById('longitude2').value = latlng.lng();
 334:         document.getElementById('latitude2').value  = latlng.lat();
 335:         document.getElementById('center').value = '';
 336:         document.getElementById('distance').value = '';
 337:         {$submit}
 338:     });
 339: 
 340:     /**
 341:      * 地図を最適サイズにフィットする
 342:      * @param   なし
 343:      * @return  なし
 344:     */
 345:     function fitting() {
 346:         var lat0, lng0, lat1, lng1;
 347:         var lat = Array();
 348:         var lng = Array();
 349:         lat[0] = document.getElementById('latitude1').value;
 350:         lng[0] = document.getElementById('longitude1').value;
 351:         lat[1] = document.getElementById('latitude2').value;
 352:         lng[1] = document.getElementById('longitude2').value;
 353:         lat[2] = {$latitude};
 354:         lng[2] = {$longitude};
 355: 
 356:         //南西端(lat0, lng0), 北東端(lat1, lng1)を求める
 357:         if (lat[0] <= lat[1]) {
 358:             lat0 = lat[0];
 359:             lat1 = lat[1];
 360:         } else {
 361:             lat0 = lat[1];
 362:             lat1 = lat[0];
 363:         }
 364:         if (lat[2] >= 0) {
 365:             if (lat[0] <= lat[2]) {
 366:                 lng0 = lng[0];
 367:                 lng1 = lng[1];
 368:             } else {
 369:                 lng0 = lng[1];
 370:                 lng1 = lng[0];
 371:             }
 372:         } else {
 373:             if (lat[0] <= lat[2]) {
 374:                 lng0 = lng[1];
 375:                 lng1 = lng[0];
 376:             } else {
 377:                 lng0 = lng[0];
 378:                 lng1 = lng[1];
 379:             }
 380:         }
 381: 
 382:         var bounds = new google.maps.LatLngBounds(new google.maps.LatLng(lat0, lng0), new google.maps.LatLng(lat1, lng1));
 383:         map.fitBounds(bounds);                      //地図表示の最適化
 384:     }
 385: 
 386: EOT;
 387:     return $js;
 388: }

ユーザー関数 jsDragMarker_Gmap は、Googleマップにマーカーを設定し、フィット機能を実装するためのJavaScriptを生成する。

中心点と対角点を示すマーカーはドラッグ可能とし、ドラッグ・イベントをフックし、緯度・経度をformオブジェクトに代入するようにする。

フィット機能は、図形の南西端と北東端を求め、GoogleマップAPIのメソッド fitBounds を呼び出すことで実現している。

drawArea.php

 390: /**
 391:  * 円描画スクリプト:Googleマップ用
 392:  * @param   int    $id          識別ID
 393:  * @param   float  $lat, $lng   中心座標(緯度,経度)
 394:  * @param   float  $radius      半径(キロメートル)
 395:  * @param   string $color       描画色(RGB)
 396:  * @param   string $fillcolor   塗りつぶし色(RGB)
 397:  * @param   float  $opacity     塗りつぶしの不透明度(0.0~1.0;省略時=1.0)
 398:  * @param   int    $weight      線の太さ(省略時=1)
 399:  * @return  string JavaScript
 400: */
 401: function jsDrawCircle_Gmap($id, $lat, $lng, $radius, $color, $fillcolor, $opacity=1.0, $weight=1) {
 402:     $radius *1000;
 403:     $js =<<< EOT
 404: var pcircle{$id} = new google.maps.Circle({
 405:     map: map,
 406:     center: { lat: {$lat}, lng: {$lng} },
 407:     radius: {$radius},
 408:     strokeColor: "#{$color}",
 409:     strokeOpacity: 1.0,
 410:     fillColor: "#{$fillcolor}",
 411:     fillOpacity: {$opacity},
 412:     strokeWeight: {$weight},
 413:     zIndex: 1
 414: });
 415: 
 416: EOT;
 417:     return $js;
 418: }

drawArea.php

 420: /**
 421:  * 矩形描画スクリプト:Googleマップ用
 422:  * @param   int    $id          識別ID
 423:  * @param   float  $lat1, $lng1 北東端の緯度・経度
 424:  * @param   float  $lat2, $lng2 南西端の緯度・経度
 425:  * @param   string $color       描画色(RGB)
 426:  * @param   string $fillcolor   塗りつぶし色(RGB)
 427:  * @param   float  $opacity     塗りつぶしの不透明度(0.0~1.0;省略時=1.0)
 428:  * @param   int    $weight      線の太さ(省略時=1)
 429:  * @return  string JavaScript
 430: */
 431: function jsDrawRectangle_Gmap($id, $lat1, $lng1, $lat2, $lng2, $color, $fillcolor, $opacity=1.0, $weight=1) {
 432:     $js =<<< EOT
 433: var prect{$id} = new google.maps.Rectangle({
 434:     map: map,
 435:     bounds: {
 436:         north: {$lat1},
 437:         south: {$lat2},
 438:         east:  {$lng1},
 439:         west:  {$lng2}
 440:     },
 441:     strokeColor: "#{$color}",
 442:     strokeOpacity: 1.0,
 443:     fillColor: "#{$fillcolor}",
 444:     fillOpacity: {$opacity},
 445:     strokeWeight: {$weight},
 446:     zIndex: 1
 447: });
 448: 
 449: EOT;
 450:     return $js;
 451: }

円や矩形を描画するユーザー関数は、GoogleマップAPIの機能をそのまま呼び出すものである。

Leaflet での図形描画

drawArea.php

 454: /**
 455:  * マーカー設定、フィット機能スクリプト:Leafletマップ用
 456:  * @param   float $latitude, $longitude 経路の中央点座標(緯度・経度)
 457:  * @param   bool  $drag TRUE:ドラッグで再描画する/FALSE:しない(デフォルト)
 458:  * @return  string JavaScript
 459: */
 460: function jsDragMarker_Leaflet($latitude, $longitude, $drag=FALSE) {
 461:     $submit = $drag ? 'document.myform.submit();' : '';
 462: 
 463:     $js =<<< EOT
 464:     // イベント設定
 465:     document.getElementById('fit').addEventListener('click', fitting, false);
 466: 
 467:     // マーカー設定
 468:     marker_001.dragging.enable();
 469:     marker_001.on('dragend', function(event) {
 470:         var marker = event.target;
 471:         var position = marker.getLatLng();
 472:         marker.setLatLng(new L.LatLng(position.lat, position.lng),{draggable:'true'});
 473:         map.panTo(new L.LatLng(position.lat, position.lng))
 474:         document.getElementById('longitude1').value = position.lng;
 475:         document.getElementById('latitude1').value  = position.lat;
 476:         document.getElementById('center').value = '';
 477:         document.getElementById('distance').value = '';
 478:         {$submit}
 479:     });
 480: 
 481:     marker_002.dragging.enable();
 482:     marker_002.on('dragend', function(event) {
 483:         var marker = event.target;
 484:         var position = marker.getLatLng();
 485:         marker.setLatLng(new L.LatLng(position.lat, position.lng),{draggable:'true'});
 486:         map.panTo(new L.LatLng(position.lat, position.lng))
 487:         document.getElementById('longitude2').value = position.lng;
 488:         document.getElementById('latitude2').value  = position.lat;
 489:         document.getElementById('diagonal').value = '';
 490:         document.getElementById('distance').value = '';
 491:         {$submit}
 492:     });
 493: 
 494:     /**
 495:      * 地図を最適サイズにフィットする
 496:      * @param   なし
 497:      * @return  なし
 498:     */
 499:     function fitting() {
 500:         var lat0, lng0, lat1, lng1;
 501:         var lat = Array();
 502:         var lng = Array();
 503:         lat[0] = document.getElementById('latitude1').value;
 504:         lng[0] = document.getElementById('longitude1').value;
 505:         lat[1] = document.getElementById('latitude2').value;
 506:         lng[1] = document.getElementById('longitude2').value;
 507:         lat[2] = {$latitude};
 508:         lng[2] = {$longitude};
 509: 
 510:         // 南西端(lat0, lng0), 北東端(lat1, lng1)を求める
 511:         if (lat[0] <= lat[1]) {
 512:             lat0 = lat[0];
 513:             lat1 = lat[1];
 514:         } else {
 515:             lat0 = lat[1];
 516:             lat1 = lat[0];
 517:         }
 518:         if (lat[2] >= 0) {
 519:             if (lat[0] <= lat[2]) {
 520:                 lng0 = lng[0];
 521:                 lng1 = lng[1];
 522:             } else {
 523:                 lng0 = lng[1];
 524:                 lng1 = lng[0];
 525:             }
 526:         } else {
 527:             if (lat[0] <= lat[2]) {
 528:                 lng0 = lng[1];
 529:                 lng1 = lng[0];
 530:             } else {
 531:                 lng0 = lng[0];
 532:                 lng1 = lng[1];
 533:             }
 534:         }
 535: 
 536:         var bounds = L.latLngBounds([lat0, lng0], [lat1, lng1])
 537:         map.fitBounds(bounds);      // 地図表示の最適化
 538:     }
 539: EOT;
 540:     return $js;
 541: }

ユーザー関数 jsDragMarker_Leaflet は、Leafletにマーカーを設定し、フィット機能を実装するためのJavaScriptを生成する。

中心点と対角点を示すマーカーはドラッグ可能とし、ドラッグ・イベントをフックし、緯度・経度をformオブジェクトに代入するようにする。

フィット機能は、図形の南西端と北東端を求め、Leafletのメソッド fitBounds を呼び出すことで実現している。

drawArea.php

 543: /**
 544:  * 円描画スクリプト:Leafletマップ用
 545:  * @param   int    $id          識別ID
 546:  * @param   float  $lat, $lng   中心座標(緯度,経度)
 547:  * @param   float  $radius      半径(キロメートル)
 548:  * @param   string $color       描画色(RGB)
 549:  * @param   string $fillcolor   塗りつぶし色(RGB)
 550:  * @param   float  $opacity     塗りつぶしの不透明度(0.0~1.0;省略時=1.0)
 551:  * @param   int    $weight      線の太さ(省略時=1)
 552:  * @return  string JavaScript
 553: */
 554: function jsDrawCircle_Leaflet($id, $lat, $lng, $radius, $color, $fillcolor, $opacity=1.0, $weight=1) {
 555:     $radius *1000;
 556:     $js =<<< EOT
 557: var pcircle{$id} = new L.Circle(
 558:     [{$lat}, {$lng}],
 559:     {
 560:         radius: {$radius},
 561:         color: "#{$color}",
 562:         weight: {$weight},
 563:         fillColor: "#{$fillcolor}",
 564:         fillOpacity: "{$opacity}"
 565:     }
 566: ).addTo(map);
 567: 
 568: EOT;
 569:     return $js;
 570: }

drawArea.php

 572: /**
 573:  * 矩形描画スクリプト:Leafletマップ用
 574:  * @param   int    $id          識別ID
 575:  * @param   float  $lat1, $lng1 北東端の緯度・経度
 576:  * @param   float  $lat2, $lng2 南西端の緯度・経度
 577:  * @param   string $color       描画色(RGB)
 578:  * @param   string $fillcolor   塗りつぶし色(RGB)
 579:  * @param   float  $opacity     塗りつぶしの不透明度(0.0~1.0;省略時=1.0)
 580:  * @param   int    $weight      線の太さ(省略時=1)
 581:  * @return  string JavaScript
 582: */
 583: function jsDrawRectangle_Leaflet($id, $lat1, $lng1, $lat2, $lng2, $color, $fillcolor, $opacity=1.0, $weight=1) {
 584:     $js =<<< EOT
 585: var prect{$id} = new L.Polygon(
 586:     [
 587:         [{$lat1}, {$lng1}],
 588:         [{$lat1}, {$lng2}],
 589:         [{$lat2}, {$lng2}],
 590:         [{$lat2}, {$lng1}]
 591:     ], {
 592:         color: "#{$color}",
 593:         weight: {$weight},
 594:         fillColor: "#{$fillcolor}",
 595:         fillOpacity: "{$opacity}"
 596:     }
 597: ).addTo(map);
 598: 
 599: EOT;
 600:     return $js;
 601: }

円や矩形を描画するユーザー関数は、Leafletの機能をそのまま呼び出すものである。

解説:カラーコード、透明度

drawArea.php

 253: /**
 254:  * カラーコード、透明度を取得する
 255:  * @param   string $key     パラメータ名(省略不可)
 256:  * @param   string $color   16進カラーコードの初期値(省略時:#FFFFFF)
 257:  * @param   float  $opacity 透明度の初期値(省略時:1.0)
 258:  * @return  bool array(#を除く16進カラーコード,透明度0.0~1.0)/FALSE=入力値が不正
 259: */
 260: function getColor($key, $color='#FFFFFF', $opacity=1.0) {
 261:     $pat = array(
 262:         0 => '/\#([0-9a-f]+)/i',
 263:         1 => '/rgb\(\s*([0-9]+)\s*\,\s*([0-9]+)\s*\,\s*([0-9]+)\)/i',
 264:         2 => '/rgba\(\s*([0-9]+)\s*\,\s*([0-9]+)\s*\,\s*([0-9]+)\s*\,\s*([0-9\.]+)\)/i'
 265:     );
 266:     $str = getParam($key, FALSE, $color);
 267:     if (preg_match($pat[0], $str, $arr> 0) {
 268:         $color = $arr[1];
 269:         $res = array($color, $opacity);
 270:     } else if (preg_match($pat[1], $str, $arr> 0) {
 271:         $color = sprintf('%02X%02X%02X', $arr[1], $arr[2], $arr[3]);
 272:         $res = array($color, $opacity);
 273:     } else if (preg_match($pat[2], $str, $arr> 0) {
 274:         $color = sprintf('%02X%02X%02X', $arr[1], $arr[2], $arr[3]);
 275:         $opacity = (double)$arr[4];
 276:         $res = array($color, $opacity);
 277:     } else {
 278:         $res = FALSE;
 279:     }
 280: 
 281:     return $res;
 282: }

ユーザー関数 getColor は、冒頭で紹介したカラーピッカー Spectrum によって得られたカラーコードや透明度を取得する。
カラーコードはrgbで始まる3つの16進数なので、関数  preg_match  を使って分解、取得する。透明度(アルファチャネル)がある場合はrgbaで始まる3つの16進数と、最後に透明度を示す10進小数があるので、同様に取得する。

drawArea.php

 284: /**
 285:  * カラーコード、透明度をrgb文字列に変換
 286:  * @param   string $color   16進カラーコードの初期値
 287:  * @param   float  $opacity 透明度の初期値(省略可能)
 288:  * @return  string rgb文字列($opacity省略時はrgb、それ以外はrgba)
 289: */
 290: function color2rgb($color, $opacity='') {
 291:     $pat = '/([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i';
 292:     if (preg_match($pat, $color, $arr> 0) {
 293:         $res = sprintf('%d, %d, %d', hexdec($arr[1]), hexdec($arr[2]), hexdec($arr[3]));
 294:         if ($opacity == '') {
 295:             $res = sprintf('rgb(%s)', $res);
 296:         } else {
 297:             $res = sprintf('rgba(%s, %f)', $res, $opacity);
 298:         }
 299:     } else {
 300:         $res = FALSE;
 301:     }
 302:     return $res;
 303: }

getColor とは逆に、URLパラメータから得られたカラーコードや透明度をカラーピッカー Spectrum に代入する必要があるので、逆関数 color2rgb を用意した。

活用例

地図上に、任意の円や矩形を描く」(みんなの知識 ちょっと便利帳)では、このサンプル・プログラムを活用し、より見やすいページを作成していただいた。ありがとうございます。

参考サイト

(この項おわり)
header