◆Google Maps API V3 + Directions API (トータルの合計距離を表示させたい)
デモギャラリーサンプルをいじってみたが、何か足りん。
そう、地図右側に表示されるルート表示のサイドバーでは、トータルの距離がわからないのである。ぐっ不便。
しかしながら、デモギャラリーでなく、Google Maps Javascript API V3 Examplesのサンプルを見ていたらtotal distanceを表示したサンプルが・・・。
せっかくなので、MarkerClustererと組み合わせて、MarkerClustererで表示されたアイコン間をドライブした気分でルート検索した合計距離を表示させてみる。
◆script
<script type="text/javascript"> var center = new google.maps.LatLng(35.62674, 139.75880); var zoom = 13; var mapTypeId = google.maps.MapTypeId.ROADMAP </script> <script type="text/javascript"> //<![CDATA[ var directionDisplay; var directionsService = new google.maps.DirectionsService(); var map; var origin = null; var destination = null; var waypoints = []; var directionmarkers = []; var directionsVisible = false; google.load('search','1'); var mcmarkers = []; var customIcons = { kouen: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/tree.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/tree.shadow.png' }, oyogu: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/swimming.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/swimming.shadow.png' }, temapark: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/motorcycling.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/cycling.shadow.png' }, sakana: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/water.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/water.shadow.png' }, suizokukan: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/fishing.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/fishing.shadow.png' }, onsen: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/hotsprings.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/hotsprings.shadow.png' }, doubutsu: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/horsebackriding.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/horsebackriding.shadow.png' }, outdoor: { icon: 'http://maps.google.com/mapfiles/ms/micons/sunny.png', shadow: 'http://maps.google.com/mapfiles/ms/micons/sunny.shadow.png' }, maturi: { icon: 'http://waox.main.jp/maps/gif/illust2212_thumb.gif', shadow: 'http://waox.main.jp/maps/gif/shadow-illust2212_thumb.png' }, sakura: { icon: 'http://waox.main.jp/maps/gif/sakura-ai.gif', shadow: 'http://waox.main.jp/maps/gif/shadow-sakura-ai.png' }, momiji: { icon: 'http://waox.main.jp/maps/gif/momiji01_002.gif', shadow: 'http://waox.main.jp/maps/gif/shadow-momiji01_002.png' }, kaisui: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/waterfalls.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/waterfalls.shadow.png' }, mikaku: { icon: 'http://waox.main.jp/maps/gif/budou01_s.gif', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/info.shadow.png' }, fuyu: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/snowflake_simple.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/snowflake_simple.shadow.png' }, banga: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/rangerstation.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/rangerstation.shadow.png' }, bbq: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/firedept.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/firedept.shadow.png' }, event: { icon: 'http://maps.google.com/mapfiles/ms/micons/volcano.png', shadow: 'http://maps.google.com/mapfiles/ms/micons/volcano.shadow.png' }, hakubutsukan: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/info.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/info.shadow.png' }, camping: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/campground.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/campground.shadow.png' }, drivespot: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/ltblu-pushpin.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/pushpin_shadow.png' }, kanko: { icon: 'http://maps.google.com/mapfiles/ms/micons/camera.png', shadow: 'http://maps.google.com/mapfiles/ms/micons/camera.shadow.png' }, restaurant: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/restaurant.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/restaurant.shadow.png' }, restaurant: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/restaurant.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/restaurant.shadow.png' }, hotel: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/homegardenbusiness.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/homegardenbusiness.shadow.png' }, shop: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/shopping.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/convienancestore.shadow.png' }, camera: { icon: 'http://maps.google.com/mapfiles/ms/micons/webcam.png', shadow: 'http://maps.google.com/mapfiles/ms/micons/webcam.shadow.png' }, ski: { icon: 'http://maps.google.com/mapfiles/ms/micons/ski.png', shadow: 'http://maps.google.com/mapfiles/ms/micons/ski.shadow.png' }, car: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/cabs.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/cabs.shadow.png' }, rail: { icon: 'http://maps.google.com/mapfiles/ms/micons/rail.png', shadow: 'http://maps.google.com/mapfiles/ms/micons/rail.shadow.png' }, parking: { icon: 'http://maps.google.co.jp/mapfiles/ms/icons/parkinglot.png', shadow: 'http://maps.google.co.jp/mapfiles/ms/icons/parkinglot.shadow.png' } }; function initialize() { var myOptions = { zoom: zoom, center: center, mapTypeId: mapTypeId }; gbarOptions= { // we're going with the defaults }; map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); var gbar=new window.jeremy.jGoogleBar(map,gbarOptions); map.controls[google.maps.ControlPosition.BOTTOM_LEFT].push(gbar.container); directionsDisplay = new google.maps.DirectionsRenderer({draggable: true}); directionsDisplay.setMap(map); directionsDisplay.setPanel(document.getElementById("directionsPanel")); google.maps.event.addListener(directionsDisplay, 'directions_changed', function() {//◆総距離合計 computeTotalDistance(directionsDisplay.directions); }); google.maps.event.addListener(map, 'click', function(event) { if (origin == null) { origin = event.latLng; addMarker(origin); } else if (destination == null) { destination = event.latLng; addMarker(destination); } else { if (waypoints.length < 9) { waypoints.push({ location: destination, stopover: true }); destination = event.latLng; addMarker(destination); } else { alert("Way Pointは、これ以上設定できません。"); } } }); downloadUrl("http://waox.main.jp/news/maps/googlemapsapi/example/cluster2-demo.php", function(data) { var infoWindow = new google.maps.InfoWindow; var cmarkers = data.documentElement.getElementsByTagName("marker"); for (var i = 0; i < cmarkers.length; i++) { var name = cmarkers[i].getAttribute("name"); var explanation = cmarkers[i].getAttribute("explanation"); var category = cmarkers[i].getAttribute("category"); var point = new google.maps.LatLng( parseFloat(cmarkers[i].getAttribute("lat")), parseFloat(cmarkers[i].getAttribute("lng"))); var linkurl = cmarkers[i].getAttribute("linkurl"); var html = '<div style="height: 150px; width: 200px"><b>'+name+'</b><br>'+explanation+'</b><br>'+linkurl+'</b>' + '<form action="http://maps.google.co.jp/maps" method="get" target="_blank">' + '<input value="ここへのルート検索" type="submit">' + '<input type="hidden" name="daddr" value="' + point.lat() + ',' + point.lng() + '"/>' ; var icon = customIcons[category] || {}; var marker = new google.maps.Marker( { map: map, position: point, icon: icon.icon, shadow: icon.shadow, title: name }); bindInfoWindow(marker, map, infoWindow, html); function bindInfoWindow(marker, map, infoWindow, html) { google.maps.event.addListener(marker, 'click', function() { infoWindow.setContent(html); infoWindow.open(map, marker); }); } mcmarkers.push(marker); } var markerCluster = new MarkerClusterer(map, mcmarkers,{gridSize: 200,maxZoom:11}); }); } function addMarker(latlng) { directionmarkers.push(new google.maps.Marker( { position: latlng, map: map, icon: "http://maps.google.com/mapfiles/marker" + String.fromCharCode(directionmarkers.length + 65) + ".png" })); } function calcRoute() { if (origin == null) { alert("Click on the map to add a start point"); return; } if (destination == null) { alert("Click on the map to add an end point"); return; } var mode; switch (document.getElementById("mode").value) { case "driving": mode = google.maps.DirectionsTravelMode.DRIVING; break; case "walking": mode = google.maps.DirectionsTravelMode.WALKING; break; } var request = { origin: origin, destination: destination, waypoints: waypoints, travelMode: mode, optimizeWaypoints: document.getElementById('optimize').checked, avoidHighways: document.getElementById('highways').checked, avoidTolls: document.getElementById('tolls').checked }; directionsService.route(request, function(response, status) { if (status == google.maps.DirectionsStatus.OK) { directionsDisplay.setDirections(response); } }); clearMarkers(); directionsVisible = true; } function updateMode() { if (directionsVisible) { calcRoute(); } } function clearMarkers() { for (var i = 0; i < directionmarkers.length; i++) { directionmarkers[i].setMap(null); } } function clearWaypoints() { directionmarkers = []; origin = null; destination = null; waypoints = []; directionsVisible = true; } //◆総距離合計 function computeTotalDistance(result) { var total = 0; var myroute = result.routes[0]; for (i = 0; i < myroute.legs.length; i++) { total += myroute.legs[i].distance.value; } total = total / 1000. document.getElementById("total").innerHTML = total + " km"; } function reset() { clearMarkers(); clearWaypoints(); directionsDisplay.setMap(null); directionsDisplay.setPanel(null); directionsDisplay = new google.maps.DirectionsRenderer({draggable: true}); directionsDisplay.setMap(map); directionsDisplay.setPanel(document.getElementById("directionsPanel")); //◆総距離合計リセット google.maps.event.addListener(directionsDisplay, 'directions_changed', function() { computeTotalDistance(directionsDisplay.directions); }); } google.setOnLoadCallback(initialize);//◆ローカルサーチ用 //]]> </script>
◆html
<!--ここからGoogle Maps v3用--> <table style="width: 400px"> <tr> <td><input type="checkbox" id="optimize" checked="checked" />ルート最適化</td> <td><input type="checkbox" id="highways" />一般道優先</td> <td><input type="checkbox" id="tolls" />有料道路を避ける</td> </tr> <tr> <td> <select id="mode" onchange="updateMode()"> <option value="driving">自動車</option> <option value="walking">徒歩</option> </select> </td> <td><input type="button" value="リセット" onclick="reset()" /></td> <td><input type="button" value="ルートを検索する。" onclick="calcRoute()" /></td> </tr> </table> <div style="position:relative; border: 1px; width : 965px; height : 596px;"> <div id="map_canvas" style="border: 1px solid black; position:absolute; width : 677px; height : 581px; top : 6px; left : -11px;"></div> <div id="directionsPanel" style="position:absolute; left : 682px; width : 263px; height : 575px; overflow: auto; top : 0px; "> <p>合計距離: <span id="total"></span></p> </div> </div> <!--ここまでGoogle Maps v3用-->
◆サンプルページ
なかなか楽しい。MarkerClustererで表示させたアイコンが邪魔。クリックするとインフォウィンドウが開いてしまう。適当にアイコンの近くをクリックしてルートを表示させてから、緑色のマーカーを動かせば良いかな?
iPhone用にこのクリックして表示させるのはいいかも。操作性が良さそう。iPhone(アイフォン)画面をタップして、赤色マーカーでドライブルートを検索するなんて使い方が出来そう。iPhone(アイフォン)アプリのGoogle Mapルート(経路)検索では、複数のWaypointを簡単に追加できないし・・・・・うーむ。こっちの方がいい気が・・・・・。次回試してみよう。
ちなみにiPhone上でこのURLhttp://maps.google.co.jp/maps?をクリックするとiPhone(アイフォン)アプリのGoogle Mapルート(経路)検索で東京-大阪間のルート結果が表示されます。
◆Google Maps JavaScript API V3
関連記事一覧
スポンサードリンク
Leave a Comment