◆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