実行例
サンプル・プログラム
photomapwin.exe | 実行型プログラム |
photomapwin.bcp | プロジェクトファイル |
photomapwin/photomapwin.phpw | サンプル・プログラム本体 |
photomapwin/photomapwin.rc | WinAsm用ソース |
photomapwin/application.ico | アイコン・ファイル |
photomapwin/*.rc | WinBinber用DLL |
photomapwin/ext/ | WinBinber用拡張ファイル |
photomapwin/include/ | WinBinber用拡張includeファイル |
photomapwin/icon/ | アイコン・ファイル |
準備:地図描画サービスの選択
地理院地図、OSM(OpenStreetMap)は無償利用できる。
2018年(平成30年)7月16日から、Google Maps API を呼び出すのにキーが必要になった。キーは無料で入手できるが、Googleアカウント を持っていること前提になる。
「Google Maps Platform」にアクセスし、Googleアカウントを使ってログインする。次に、右上の「スタートガイド」か左下の「使ってみる」をクリックすると、キー入手方法を知ることができる。
キーを入手したら、定数 GOOGLE_API_KEY に代入する。
解説:HTMLコントロール
0566: //HTMLControlの設定
0567: wb_create_control($window, HTMLControl, 'JSmap', 10, 280, 750, 400, IDC_GMAP_HTML);
0229: //マップ表示
0230: $res = getGPS($exif, $latitude, $longitude);
0231: if ($res) {
0232: switch (MAPSERVICE) {
0233: case 0:
0234: $html = drawGMap($latitude, $longitude, 10);
0235: break;
0236: default:
0237: $html = drawLeaflet($latitude, $longitude, 10);
0238: break;
0239: }
0240: $outfp = fopen($Tempfname, 'w');
0241: fwrite($outfp, $html);
0242: fclose($outfp);
0243: wb_set_location(wb_get_control($window, IDC_GMAP_HTML), $Tempfname);
0244: } else {
0245: wb_set_location(wb_get_control($window, IDC_GMAP_HTML), 'cmd:blank');
0246: put_error($window, ERROR_NOTGPS);
0247: }
0248:
0249: //Exif情報表示
0250: wb_create_items(wb_get_control($window, IDC_EXIF_LISTVIEW), $exif);
解説:Googleマップ
0276: /**
0277: * Googleマップを描く
0278: * @param double $latitude 中心座標:緯度(世界測地系)
0279: * @param double $longitude中心座標:経度(世界測地系)
0280: * @param int $zoom 拡大率
0281: * @return string Googleマップのコード
0282: */
0283: function drawGMap($latitude, $longitude, $zoom) {
0284: $encode = 'UTF-8';
0285: $title = TITLE;
0286: $id = 'gmap_spot';
0287: $key = GOOGLE_API_KEY;
0288: $type = 'ROADMAP';
0289:
0290: $code =<<< EOD
0291: <!DOCTYPE html>
0292: <html lang="ja">
0293: <head>
0294: <meta charset="{$encode}">
0295: <title>{$title}</title>
0296: <meta name="author" content="studio pahoo" />
0297: <meta name="copyright" content="studio pahoo" />
0298: <meta name="ROBOTS" content="NOINDEX,NOFOLLOW" />
0299: <meta http-equiv="pragma" content="no-cache">
0300: <meta http-equiv="cache-control" content="no-cache">
0301: <meta http-equiv="X-UA-Compatible" content="IE=edge">
0302: </head>
0303: <body>
0304: <script src="https://maps.googleapis.com/maps/api/js?key={$key}&callback=initMap&region=JP" async defer></script>
0305: <script>
0306: function initMap() {
0307: var map = new google.maps.Map(document.getElementById('{$id}'), {
0308: center: new google.maps.LatLng({$latitude}, {$longitude}),
0309: zoom: {$zoom},
0310: mapTypeId: google.maps.MapTypeId.{$type},
0311: mapTypeControl: true,
0312: scaleControl: true
0313: });
0314: var marker = new google.maps.Marker({
0315: position: new google.maps.LatLng({$latitude}, {$longitude}),
0316: map: map,
0317: title: '',
0318: zIndex: 999
0319: });
0320: }
0321: </script>
0322: <div id="{$id}" style="width:720px; height:370px;"></div>
0323: </body>
0324: </html>
0325:
0326: EOD;
0327:
0328: return $code;
0329: }
解説:地理院地図・OSM
0331: /**
0332: * Leafletによるマップ描画
0333: * @param double $latitude 中心座標:緯度(世界測地系)
0334: * @param double $longitude中心座標:経度(世界測地系)
0335: * @param int $zoom 拡大率
0336: * @return string Leafletマップのコード
0337: */
0338: function drawLeaflet($latitude, $longitude, $zoom) {
0339: $encode = 'SJIS';
0340: $title = TITLE;
0341: $id = 'lmap';
0342: $type = 'OSM';
0343:
0344: $code =<<< EOD
0345: <!DOCTYPE html>
0346: <html lang="ja">
0347: <head>
0348: <meta charset="{$encode}">
0349: <title>{$title}</title>
0350: <meta name="author" content="studio pahoo" />
0351: <meta name="copyright" content="studio pahoo" />
0352: <meta name="ROBOTS" content="NOINDEX,NOFOLLOW" />
0353: <meta http-equiv="pragma" content="no-cache">
0354: <meta http-equiv="cache-control" content="no-cache">
0355: <meta http-equiv="X-UA-Compatible" content="IE=edge">
0356: <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" />
0357: <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script>
0358: <script>
0359: window.onload = function() {
0360: var map = L.map('{$id}',{zoomControl:false});
0361: map.setView([{$latitude}, {$longitude}], {$zoom});
0362: L.control.scale({
0363: maxWidth: 200,
0364: position: 'bottomright',
0365: imperial: false
0366: }).addTo(map);
0367: L.control.zoom({position:'topleft'}).addTo(map);
0368:
0369: //地理院地図:標準地図
0370: var GSISTD = new L.tileLayer(
0371: 'https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png',
0372: {
0373: attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>",
0374: minZoom: 0,
0375: maxZoom: 18,
0376: name: 'GSISTD'
0377: });
0378: //地理院地図:淡色地図
0379: var GSIPALE = new L.tileLayer(
0380: 'https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png',
0381: {
0382: attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>",
0383: minZoom: 2,
0384: maxZoom: 18,
0385: name: 'GSIPALE'
0386: });
0387: //地理院地図:白地図
0388: var GSIBLANK = new L.tileLayer(
0389: 'https://cyberjapandata.gsi.go.jp/xyz/blank/{z}/{x}/{y}.png',
0390: {
0391: attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>",
0392: minZoom: 5,
0393: maxZoom: 14,
0394: name: 'GSIBLANK'
0395: });
0396: //地理院地図:写真
0397: var GSIPHOTO = new L.tileLayer(
0398: 'https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg',
0399: {
0400: attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>",
0401: minZoom: 2,
0402: maxZoom: 18,
0403: name: 'GSIPHOTO'
0404: });
0405: //OpenStreetMap
0406: var OSM = new L.tileLayer(
0407: 'https://tile.openstreetmap.jp/{z}/{x}/{y}.png',
0408: {
0409: attribution: "(c) <a href='https://osm.org/copyright' target='_blank'>OpenStreetMap</a> contributors",
0410: minZoom: 0,
0411: maxZoom: 18,
0412: name: 'OSM'
0413: });
0414:
0415: //baseMapsオブジェクトにタイル設定
0416: var baseMaps = {
0417: "地理院地図" : GSISTD,
0418: "淡色地図" : GSIPALE,
0419: "白地図" : GSIBLANK,
0420: "写真地図" : GSIPHOTO,
0421: "オープンストリートマップ" : OSM
0422: };
0423:
0424: //layersコントロールにbaseMapsオブジェクトを設定して地図に追加
0425: L.control.layers(baseMaps).addTo(map);
0426: {$type}.addTo(map);
0427:
0428: //マーカー
0429: var icon = new L.marker([{$latitude}, {$longitude}]).addTo(map);
0430: }
0431: </script>
0432: <div id="{$id}" style="width:720px; height:370px;"></div>
0433: </body>
0434: </html>
0435:
0436: EOD;
0437:
0438: return $code;
0439: }
解説:マップ描画
0569: //テンポラリ・ファイルの設定
0570: $path = getenv('TEMP');
0571: //環境変数TEMPあり
0572: if (file_exists($path)) {
0573: $Tempfname = tempnam($path, 'gmp');
0574: //環境変数TEMPなし
0575: } else {
0576: $path = TEMPPATH;
0577: @mkdir($path);
0578: if (! file_exists($path)) exit(1);
0579: $Tempfname = realpath(tempnam($path, 'gmg'));
0580: }
一時ファイルの保存先は、環境変数 TEMP が定義されていれば、組み込み関数 getenv で取得し、無ければユーザー定数 TEMPPATH で定義したフォルダを作成し、そこに一時ファイルとして作成する。
プログラム終了時に組み込み関数 unlink を使って削除することをお忘れなく。
コンパイル
参考サイト
- PHPでExif情報を表示する(Windowsアプリ版):ぱふぅ家のホームページ
- PHPで最寄りのネットができるホテルを検索する:ぱふぅ家のホームページ
- PHPで住所・ランドマークから最寄り駅を求める:ぱふぅ家のホームページ
今回は、Exif情報の中にある位置情報(GPS情報)を Googleマップ、地理院地図、OpenStreetMap のいずれかにマッピングするようにプログラムを拡張する。
なお、後述するように、2018年(平成30年)7月から Google Maps APIキーが必須となったため、本プログラムでは無償の 地理院地図、OpenStreetMap を選択した状態でコンパイルした実行型プログラムを同梱している。