リスト1は今回のサンプルでの地図・動画情報管理の部分です。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>Google Maps API</title> <script type="text/javascript" src="/jslib/gaedirect.js"></script> <script type="text/javascript" src="/jslib/jquery-1.5.min.js"></script> <script src="http://maps.google.com/maps?file=api&v=2&key=ABQIAAAA7BH7CggsNmHOlKjr9pP9WBQQHituv_dQvmyzddsqjI99D3nK1hTA4etykWuI0c0HB0eZzw_Lo60aZg" type="text/javascript"></script> <script type="text/javascript"> $(function(){ var query = ginit(); //(1) query["kind"] = "gmaps"; //(2) query["key"] = "none"; //(3) query["id"] = "area,lon,lat,comment,type"; //(4) var tags = ""; var lon = 0.0, lat = 0.0, comment = "", type = ""; var kind = "gmaps"; var props1 ="pref,area,do:lon,do:lat,comment,type"; //(4) var props2 ="pref,area,lon,lat,comment,type"; var propsa = props2.split(","); // データ登録 $("#add").click(function(){ var key = $("#key").val(); $.post(gae(), add(kind, key, props1), function(res){ $("#stat").html(res); }); }); // データ参照 $("#rev").click(function(){ var key = $("#key").val(); $.get(gae(),rev(kind, key, props2),function(res){ if ((res).substr(0, 3) != "NO:") { var dat= res.split("<p>"); for (var i = 0; i < props2.length; i++){ $("#"+propsa[i]).val(dat[i]); } }else{ $("#stat").html(res.substr(3)); } }); }); // データ更新 $("#upd").click(function(){ var key = $("#key").val(); $.post(gae(), upd(kind, key, props1),function(res){ $("#stat").html(res); }); }); // クリア $("#clr").click(function(){ $.each(["key","pref","area","lon","lat","comment"], function(){ $("#" + this).val(""); }); $("#stat").text(""); $("#key").focus(); }); // 地図表示 $("#revmap").click(function(){ //(5) $.get(gae(), query, function(res){ //(6) if ((res).substr(0, 3) != "NO:") { //(7) var map = new GMap2(document.getElementById("map")); //(A) map.setCenter(new GLatLng(38.688215, 140.8693558), 8); //(B) map.addControl(new GLargeMapControl()); //(C) map.addControl(new GMapTypeControl()); //(D) var pname = new Array(); var ents = res.split("<e>"); //(8) for (var i = 0; i < ents.length; i++) { //(9) area = ents[i].split("<p>")[1]; //(10) lon = ents[i].split("<p>")[2]; //(10) lat = ents[i].split("<p>")[3]; //(10) comment = ents[i].split("<p>")[4]; //(10) map.addOverlay(setMarker(lat, lon , comment)); //(E) } }else{ $("#stat").html(res.substr(3)); } }); }); // 条件検索のコード function setMarker(lat,lon, msg){ var marker = new google.maps.Marker(new google.maps.LatLng(lat, lon)); //(F) google.maps.Event.addListener(marker, "click", function() { //(G) marker.openInfoWindowHtml(msg); //(H) }); return marker; } }); </script> </head> <body> <h1 style="color: #aa0022">津波、不忘の記録</h1> <h2>2011年3月11日</h2> <p> <h3>◆動画情報管理◆</h3> <input type="button" id="add" value=" 登録 "/> <input type="button" id="rev" value=" 参照 "/> <input type="button" id="upd" value=" 更新 "/> <input type="button" id="clr" value=" クリア "/> ステータス<div id="stat"></div> キー:<input type="text" id="key" size="10"/><br/> 都県:<input type="text" id="pref" /> 地域:<input type="text" id="area" /> lon(経度):<input type="text" id="lon" size="16" /> lat(緯度):<input type="text" id="lat" size="16" /><br/> コメント:<br/> <textarea id="comment" rows="10" cols="110" wrap="hard"></textarea><br/> </p> <p> <ul id="out" type="square"></ul> <h3>◆地図情報表示◆</h3> マーカクリックで吹き出しを表示する <input type="button" id="revmap" value="地図表示"/> <div id="map" style="width:580px; height:1100px"></div> </p> </body> </html>
gaedirectでの登録・参照・更新処理については、もう何度も紹介しているので説明の必要はほとんどないと思います。
ただし今回は緯度、経度をdouble型(8bytes浮動小数点型)にしているため、(1)の登録と更新で使用されるプロパティリストでは「do」を指定しています。
Google Mapsの表示ではgaedirectによる分散KVSのデータ参照と、Google Maps APIでの地図表示処理の2つが組み合わさっているので、それぞれの処理を分けて見ていきます。
今回はgaedirectの条件検索についても紹介することになっていますが、その最初として、このサンプルでは全件検索が使用されています。
サンプルの「地図表示」ボタンをクリックすると、(5)で匿名関数が起動され、次の(6)ではgaedirectモードの$.getでサーバへの参照リクエストを行います。
ただし、ここでの参照では、これまでのキーを使用したケースとは異なり、第2引数はjQuery標準の連想配列として「query」を使用しています。このqueryに対する値設定は、リスト上部の(1)から行います。次ページで詳細を解説しますが、条件検索では基本的に、次のパターンで連想配列の値を設定します。
これで全件参照の場合の連想配列のセッティングは終わります。後は、(6)で参照リクエストを実行し、サーバ側での参照処理が正常に行われた場合は、(7)のif文判断が成立して、地図・マーカなどの表示処理に移ります。この部分ではGoogle Maps APIでの描画処理を行いますが、それについては、この後解説します。
その前に、gaedirectでの処理を見てくと、(8)でサーバからの受信データを「<e>」(エンティティ区切り)で文字列分割して配列「ents」にエンティティごとにセットし、(9)のfor文で、エンティティごとのプロパティ値を対応する変数に、それぞれ(10)でセットしています。
以上がgaedirectでの処理ですが、この処理を基にGoogle Maps(以後、GMaps)APIでの描画処理を行います。
最初にGMaps APIで地図表示を行うためには、グーグルが発行するキーを取得する必要があります。これはGoogleのクラウド上でも同様でリスト1の9行目のように<script>タグでkey値を指定してGMaps APIのライブラリ、定数などを読み込みます。
(A)のGMaps2は地図表示用のJavaScriptクラスで、描画処理の最初にnew演算子でインスタンス「map」を生成します。引数では、地図を描画するコンテナをノードオブジェクトのID値で指定しますが、ここでは幅が580px、高さが1100pxという、かなり大きなサイズにしています。これは、地図上に主要市町名が表示されるスケールを選択した結果です。
この後は、生成したインスタンス「map」のメソッドを使用した処理になっていきます。
(B)では、.setCenterで地図中心の緯度、経度とズームサイズ(ここでは「8」)を指定しています。地図中心は東北・北関東の太平洋沿岸を表示しやすい位置を指定しています。
(C)では、addControlで地図の移動とズームレベルを操作するためのコントロールを地図に追加しますが、GLargeMapControl()のインスタンスを引数に指定すると、図6の大型のコントロールが追加されます。
(D)では、同様にGMapTypeControl()のインスタンスを指定しています。これによって図7のマップタイプ選択用のコントロールが追加され、地図(Map)、衛星写真(Satellite)、およびこの2つの組み合わせ(Hybrid)で地図を表示できます。
ここで、図7のSatelliteまたはHybridを選択して地図表示のズームレベルを上げていくと、沿岸地域の衛星写真は全て津波被災後のものになっています。このことはご存じの方も多いと思います。
この後はgaedirectでの処理が少しあり、マーカの表示処理に移ります。
GMapsには地図上のポイントを示すマーカ用のアイコンが用意されており、(E)では、この標準アイコンを使用してマーカを表示しています。マーカ表示にはaddOverlayを使用しますが、引数のsetMarker指定で標準マーカが使用されます。setMarkerの引数は、その下に定義されている、setMarker関数を呼び出す形になっています。マーカが1つだけの場合は、このような関数呼び出し形式にする必要はありません。
setMarker関数では(F)のgoogle.maps.Markerでマーカを表示しますが、引数にはLatLngで生成した緯度、経度を指定します。
それぞれのマーカは、マウスでクリックすると、吹き出しを表示します。この設定は(G)と(H)で行われています。(G)のリスナ設定がGMaps特有の設定ですが、(F)で設定されたマーカのクリックイベントで(H)のopenInfoWindowHtmlメソッドが、表示データ「msg」を引数にとって実行され、吹き出しを表示します。
次ページからは話の内容を変えて、gaedirectでの条件検索機能を見ていきます。
Copyright © ITmedia, Inc. All Rights Reserved.