2009年10月21日水曜日

無線LANで現在位置を取得してGoogleマップとストリートビューで表示する

このブログ記事をはてなブックマークに追加

昨年の8月に書いた記事、「Google App Engine: Gearsで位置情報を取得してストリートビューで表示させる」で、無線LANから取得した現在位置をGoogleマップストリートビューで表示するウェブアプリを作ったが、今回、それをブログなどにもそのまま貼り付けられるようにしてみた。もともと、JavaScriptを使ったアプリなのでそれほど変更するところもなかったのだが、無用な部分を削除し、きちんと画面にエラーメッセージを表示するようにした。動作させるためにはGearsをインストールしている必要がある。

無線LANから現在位置情報を取り出すためにGearsのGeolocation APIを使った。位置情報を取り出したらあとはGoogle Maps APIでそれをGoogleマップとストリートビューで表示させるだけだ。因みに、今年の7月からGoogleマップの画面で左上にある四角いボタンを押すと現在位置を表示できるようになっている。

今回のアプリでは、現在位置を示すマーカーに自作の扇形アイコンを使った。ストリートビューの向きと連動している。ペグマン(人型アイコン)でもよかったのだろうけど、個人的には向いている方向が分かりづらいと思う。



以下にソースファイルを示す。ページを読み込んだ際にGearsにより位置情報を取得している。

<script src="http://maps.google.com/maps?file=api&v=2.x&key=Google Maps API Key" type="text/javascript"></script> <script type="text/javascript" src="http://code.google.com/apis/gears/gears_init.js"></script> <script type="text/javascript"> var map; var pano; var overlayInstance = null; var marker; var info_window = false; var lat, lng; var error_msg = ""; function updatePosition(position) { lat = position.latitude; lng = position.longitude; initialize(); } function initialize_geo() { if (window.google && google.gears) { var geo = google.gears.factory.create("beta.geolocation"); geo.getCurrentPosition(updatePosition, function(positionError) { document.getElementById("error").innerHTML = positionError.message; }); } else { error_msg = "位置情報の取得に<a href=\"http://gears.google.com/\">Gears</a>が必要です。"; document.getElementById("error").innerHTML = error_msg; // 秋葉原. lat = 35.698584; lng = 139.774216; initialize(); } } function initialize() { if (GBrowserIsCompatible()) { var latlng = new GLatLng(lat, lng); var zoom = 15; marker = new GMarker(latlng, {icon: getArrowIcon(0.0), clickable: false}); pano = new GStreetviewPanorama(document.getElementById("pano")); GEvent.addListener(pano, "error", handleNoFlash); GEvent.addListener(pano, "initialized", moveStreet); GEvent.addListener(pano, "yawchanged", yawStreet); map = new GMap2(document.getElementById("map_canvas")); GEvent.addListener(map, "click", moveWalker); map.addControl(new GSmallMapControl()); map.addControl(new GMapTypeControl()); map.setCenter(latlng, zoom); map.addOverlay(marker); map.enableScrollWheelZoom(); pano.setLocationAndPOV(latlng); toggleOverlay(); GEvent.addListener(map, "click", function(overlay, latlng) { pano.setLocationAndPOV(latlng); }); } var client = new GStreetviewClient(); client.getNearestPanorama(latlng, setNewLatLng) } function setNewLatLng(data){ if (data.code != 200) { return; } var new_latlng = data.location.latlng; pano.setLocationAndPOV(new_latlng); map.panTo(new_latlng); marker.setLatLng(new_latlng); } function getArrowIcon(bearing) { var icon = new GIcon(); icon.image = getArrowUrl(bearing); icon.iconSize = new GSize(92, 92); icon.iconAnchor = new GPoint(46, 46); return icon; } function getArrowUrl(bearing) { var id = 3 * Math.round(bearing / 3); return "view_marker_" + id + ".png"; } function moveStreet(location_) { map.setCenter(location_.latlng); marker.setLatLng(location_.latlng); document.getElementById("error").innerHTML = error_msg; } function yawStreet(yaw_) { marker.setImage(getArrowUrl(yaw_)); } function moveWalker(overlay_, latlng_) { var client = new GStreetviewClient(); client.getNearestPanorama(latlng_, setNewLatLng) } function toggleOverlay() { if (!overlayInstance) { overlayInstance = new GStreetviewOverlay(); map.addOverlay(overlayInstance); } else { map.removeOverlay(overlayInstance); overlayInstance = null; } } function toggleMarkerLocation() { if (!info_window) { pov = pano.getPOV(); var displayString = [ marker.getLatLng(), "POV yaw: " + pov.yaw, "POV pitch: " + pov.pitch, "POV zoom: " + pov.zoom ].join("<br />"); map.openInfoWindowHtml(marker.getLatLng(), displayString); info_window = true; } else { map.closeInfoWindow(); info_window = false; } } function handleNoFlash(errorCode) { if (errorCode == GStreetviewPanorama.ErrorValues.FLASH_UNAVAILABLE) { document.getElementById("error").innerHTML = "Flashがサポートされていません。"; } else if (errorCode == GStreetviewPanorama.ErrorValues.NO_NEARBY_PANO) { document.getElementById("error").innerHTML = "ストリートビューの範囲外です。"; } } if (window.attachEvent){ window.attachEvent("onload", initialize_geo); window.attachEvent("onunload", GUnload); } else { window.addEventListener("load", initialize_geo, false); window.addEventListener("unload", GUnload, false); } </script> <table><tr> <td><div id="pano" style="float:left; background-color: black; width: 250px; height: 250px"></div></td> <td><div id="map_canvas" style="width: 250px; height: 250px"></div></td> </tr></table> <div><input type="button" onclick="toggleOverlay()" value="ストリートビューレイヤー" /> <input type="button" onclick="toggleMarkerLocation()" value="現在位置" /> <span id="error"></span></div>

0 コメント: