Auld Lang Syne 2

Google Maps API を動的に使う −vol.3−
テーマ:
「Google Maps API(以下、GMA) と PHP + MySQL を連動し、表示領域に応じたデータをデータベースから取得し、地図に表示する」

検索エンジンからこられた方はvol.1よりご覧ください

map.php

<?php

/*
このスクリプトはセキュリティ処理、エラー処理等を省略しています。
運用の再には、必ず、セキュリティ処理、エラー処理を施してください。
*/

// 変数の受け取り
$minX = $_GET["minX"];
$minY = $_GET["minY"];
$manX = $_GET["maxX"];
$maxY = $_GET["maxY"];

// SQL(テーブルADDRESSBOOKから該当データを取り出すクエリ文)
$SQL = "SELECT longitude,latitude FROM ADDRESSBOOK WHERE longitude > $minX and longitude < $maxX and latitude > $minY and latitude < $maxY ";

// MySQLに接続し、クエリ文を実行
$conn = mysql_connect(- 省略 -);
mysql_select_db(- 省略 -);
$res = mysql_query($SQL,$conn);
$res_num = mysql_num_rows($res);

//以下、XML出力
// UTF-8に設定(必須!)
mb_http_output('UTF-8');
header("Content-type: text/xml; charset=UTF-8");

print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<markers>
";
$i = 0;
while($row = mysql_fetch_array($res) and $i < $res_num){
 // エンコードを変換(EUCからUTF-8の例)
 mb_convert_variables("UTF-8", "EUC-JP",$row);
 $xml = "<marker longitude=\"".$row["longitude"]."\" latitude=\"".$row["latitude"]."\" />";
 print $xml;
 $i++;
}
print "
</markers>
";

?>

このスクリプトは以下のようなXMLを出力します(というかXMLを出力するだけです)。これをmap.htmlでは、request.responseXMLとして受け取ります。

<?xml version="1.0" encoding="UTF-8"?>
<markers>
<marker longitude="139.71" latitude="35.5" />
<marker longitude="139.76" latitude="35.6" />
<marker longitude="139.80" latitude="35.7" />
</markers>

以上、map.htmlとmap.phpの組合せで、表示領域に応じてマーカーがポコポコと表示されるようになります。(各スクリプトの役割はvol.1の処理の流れを参照)

[注意事項]
データが数百件程度なら、動的にXMLを出力する必要はないと思います。

[参考サイト]
Google Maps API Documentation:GMA公式ドキュメンテーション
Google Maps API クラスリファレンス 意訳とサンプル:GMAの日本語リファレンス
Web::Blogoscope: Google Maps API解説:GMAの導入方法、基本操作の説明
真夜中ナビ 地図から探す!深夜営業のお店:実用例(ごめんなさい。宣伝です...。)

[後書き]
もっと事細かに書く予定でしたが、ソースにコメントをつけて書くだけで力つきてしまい、適度に省いてしまいました<(_ _)>
Google Maps API を動的に使う −vol.2−
テーマ:
「Google Maps API(以下、GMA) と PHP + MySQL を連動し、表示領域に応じたデータをデータベースから取得し、地図に表示する」

検索エンジンからこられた方はvol.1よりご覧ください

map.htmlのソース (表示の都合上、一部、全角記号・全角スペースを使用しております。)

<html>
<head> 省略 </head>
<body>
<div id="map" style="width:500px; height:400px"></div><!-- ここに地図を表示 -->

<script src="http://maps.google.com/maps?file=api&v=1&key="****************" type="text/javascript"></script><!-- APIキーを記述 -->

<script type="text/javascript">
//<![CDATA[
var map = new GMap(document.getElementById("map"));
map.centerAndZoom(new GPoint(139.766103, 35.681391), 4); // 地図中心(東京駅)
// ドラッグで移動終了後にエリアに対応するマーカーを表示
GEvent.addListener(map, "moveend", function() {
  map.clearOverlays(); // 表示済のマーカーを消去(※1)
  plot_marker(map);
});

// 地図上にマーカーを表示する関数 (引数mapは省略可)
function plot_marker(map){

  // 表示領域情報を取得し、クエリーストリングとしてmap.phpに受け渡す準備
  var bound = map.getBoundsLatLng(); // 表示領域情報を取得
  var url = "map.php?minX="+bound.minX+"&minY="+bound.minY+"&maxX="+bound.maxX+"&maxY="+bound.maxY;
↑表示の都合上、全角+記号を使っています。

  // XMLHttpRequestオブジェクトを生成
  var request = GXmlHttp.create();

  // GETメソッドでurlを非同期(true)に開く
  request.open("GET",url,true);

  // コールバック関数(map.phpから返されるXML(※2)を解析)
  request.onreadystatechange = function() {
    if (request.readyState == 4) {
       var res = request.responseXML;
       // XMLのmarkerタグ要素の配列markersを作る
       var markers = res.documentElement.getElementsByTagName("marker");

       // forループで地図上にマーカーを1つずつプロットしていく(※3)
       // perseFloat関数は与えられた文字型の引数を実数値に変換する関数
       for (var i = 0; i < markers.length; i++) {
         var lon = parseFloat(markers[i].getAttribute("longitude"));
         var lat = parseFloat(markers[i].getAttribute("latitude"));
         var point = new GPoint(lon,lat);
         var marker = new GMarker(point);
         map.addOverlay(marker);
      }
    }
  }
  request.send(null); // 送信
}

//]]>
</script>
</body>
</html>


表示領域情報を取得し、クエリーストリングとしてmap.phpに受け渡すことがポイントで、その他はAjax(というかGMA)の典型パターンです。

(※1)
clearOverlays() はIEでは正常に機能しないこともあるので、removeOverlay(overlay) を繰り返してマーカーをひとつずつ消していく方法を用いることが多いようです。

(※2)
map.phpからは次のようなXMLが返されます
<?xml version="1.0" encoding="UTF-8"?>
<markers>
<marker longitude="139.71" latitude="35.5" />
<marker longitude="139.76" latitude="35.6" />
<marker longitude="139.80" latitude="35.7" />
</markers>

(※3)
上のXMLの場合こんな感じになります。
parseFloat(markers[0].getAttribute("longitude")) → 139.71
parseFloat(markers[1].getAttribute("longitude")) → 139.76
parseFloat(markers[2].getAttribute("longitude")) → 139.80

vol.3ではXMLを出力するためのスクリプトmap.phpのソースサンプルを示します。
Google Maps API を動的に使う −vol.1−
テーマ:
「Google Maps API(以下、GMA) と PHP + MySQL を連動し、表示領域に応じたデータをデータベースから取得し、地図に表示する」

はじめに:
GMAについて日本語で書かれた情報が少ないので、実践的なサイト製作の参考にしていただければ幸いです。ただし、文章を書くのが苦手なので、うまく説明できていないかもしれませんが、そこのところはご容赦ください。

前提:
・Ajax(Google Maps API関係), Javascript, PHP, (MySQL)の基礎知識
・セキュリティ処理、エラー処理、カスタマイズ処理は省略(エッセンスのみ記入)

スクリプト概要:
map.html 地図を表示するスクリプト(HTML,Javascript)
map.php 表示領域に対応したデータをDBから取り出し、map.htmlにXMLを返すスクリプト(PHP)

処理の流れ
(1) map.htmlで地図領域を取得
(2) 領域をクエリーストリングとして(GETメソッドで)map.phpに受け渡し
(3) map.phpで対応するデータをDBから取り出し、XMLとして出力
(4) 出力されたXMLを受け取る(var res = request.responseXML)
(5) 受け取ったデータを地図上に表示していく(forループ)

→(2)〜(4)の過程がサーバーとの非同期通信です。
vol.2にmap.html, vol.3にmap.phpのサンプルソースを示します。
ブログ整理作業
ブログの改造を予定しています。

・技術Blog:技術系の日記・メモ・リンク。
・更新メモBlog:真夜中ナビの取り扱い説明など。更新履歴など。

Auld Lang Syne 2は技術系に使う予定です。(FC2 BLOG様は自由度が高ようなので)

もうひとつはどこか新しいところ(ブログサービス)のを借りる予定です。ここにまとめて書けば済むと言えば済むのですが....

・サイト製作者の端くれとしての探求心があるので、いろいろなところのサービスを使ってみたい
・1つの(企業の)サービスにあれこれ置くのはリスクが大きい

などなど。

とりあえずご報告。
Designed by aykm.