I want to load an itinerary from a geoJSON file. For the moment, it works, but only with two points.
But I need to add 4 or 5 waypoints. My code only read the two first
The problem is that you can't access the FeatureCollection where a feature belongs to. There is also no event that will fire when the parsing of the geoJSON has been finished(when the addfeature-event fires you'll never know if it's the last time for the particular FeatureCollection)
You may store additional properties for the features, e.g. the number of waypoints.
sample-JSON(including other properties to define e.g. if a point is a waypoint, origin or destination or when it's a waypoint the index of the waypoint )
{
"type": "FeatureCollection",
"features": [
{
"type" : "Feature",
"properties" : {route :{"id" :1,
"type" :"origin",
"points":2
}
},
"geometry" : {"type" : "Point",
"coordinates":[8.528849, 52.030656]}
},
{
"type" : "Feature",
"properties" : {route :{"id" :1,
"type" :"destination",
"points":2
}
},
"geometry" : {"type" : "Point",
"coordinates":[11.5819, 48.1351253]}
},
{
"type": "Feature",
"properties" : {"route" :{"id" :1,
"type" :"waypoint",
"index" :1,
"points":2
}
},
"geometry" : {"type" : "Point",
"coordinates":[13.40495,52.52]}
},
{
"type" : "Feature",
"properties" : {route :{"id":1,
"type":"waypoint",
"index":0,
"points":2
}
},
"geometry" : {"type" : "Point",
"coordinates":[9.99368, 53.5510846]}
}
]}
It stores the properties in a custom route
-property.
The properties are:
type
(origin,destination or waypoint)id
(some unique id for the route, by using the id you'll be able to define multiple routes)points
(the number of waypoints defined for the route)index
...used for type:waypoint(the index of the waypoint in the waypoints-array, starting with 0)parsing of these properties:
map.data.addListener('addfeature',function(e){
var geo= e.feature.getGeometry();
if(geo.getType()==='Point' && e.feature.getProperty('route')){
var id = e.feature.getProperty('route').id,
type = e.feature.getProperty('route').type,
points= e.feature.getProperty('route').points,
data;
//the routes will be stored as a property of map.data
if(!map.data.get('routes')){
map.data.set('routes',{});
}
if(!map.data.get('routes')[id]){
map.data.get('routes')[id]={waypoints:[],points:points,origin:null,destination:null};
}
data= map.data.get('routes')[id];
switch(type){
case 'waypoint':
data.points--;
data.waypoints[e.feature.getProperty('route').index]={location:geo.get()};
break;
default:
data[type]= geo.get();
}
if(!data.points && data.origin && data.destination){
//parsing of the route is complete
delete data.points;
//run the callback,
//data is an object suitable to be used as DirectionsRequest
//you only need to add the desired travelMode
callback(data);
}
}
});
Demo: http://jsfiddle.net/doktormolle/vupkbasc/
working fiddle
function calculate() {
var request = {
origin: origin,
waypoints: waypts,
destination: destination,
travelMode: google.maps.TravelMode.DRIVING
};
directionsDisplay.setPanel(document.getElementById('directions-panel'));
directionsService.route(request, function (response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
// global variables
var origin = null;
var destination = null;
var waypts = [];
var infowindow = new google.maps.InfoWindow();
var directionsDisplay = new google.maps.DirectionsRenderer();
var directionsService = new google.maps.DirectionsService();
function initialize() {
// Create a simple map.
features = [];
map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 4,
center: {
lat: -28,
lng: 137.883
}
});
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('directions-panel'));
google.maps.event.addListener(map, 'click', function () {
infowindow.close();
});
// process the loaded GeoJSON data.
google.maps.event.addListener(map.data, 'addfeature', function (e) {
if (e.feature.getGeometry().getType() === 'Point') {
map.setCenter(e.feature.getGeometry().get());
// set the origin to the first point
if (!origin) origin = e.feature.getGeometry().get();
// set the destination to the second point
else waypts.push({
location: e.feature.getGeometry().get(),
stopover: true
});
// calculate the directions once both origin and destination are set
// calculate();
}
});
google.maps.event.addListenerOnce(map, 'idle', function () {
if (!destination) {
destination = waypts.pop();
destination = destination.location;
// calculate the directions once both origin and destination are set
calculate();
}
});
map.data.addGeoJson(data);
}
google.maps.event.addDomListener(window, 'load', initialize);
To address Dr.Molle's point about the idle
event firing before the data layer is loaded, you can create a custom data_idle
event, and fire that event after all the points from the GeoJson have been processed.
updated fiddle
var features_added = 0;
function initialize() {
// Create a simple map.
features = [];
map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 4,
center: {
lat: -28,
lng: 137.883
}
});
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('directions-panel'));
google.maps.event.addListener(map, 'click', function () {
infowindow.close();
});
// process the loaded GeoJSON data.
google.maps.event.addListener(map.data, 'addfeature', function (e) {
if (e.feature.getGeometry().getType() === 'Point') {
features_added++;
map.setCenter(e.feature.getGeometry().get());
// set the origin to the first point
if (!origin) origin = e.feature.getGeometry().get();
// set the destination to the second point
else waypts.push({
location: e.feature.getGeometry().get(),
stopover: true
});
setTimeout(function() {features_added--; if (features_added <= 0) google.maps.event.trigger(map, 'data_idle');
}, 500);
}
});
google.maps.event.addListenerOnce(map, 'data_idle', function () {
if (!destination) {
destination = waypts.pop();
destination = destination.location;
// calculate the directions once both origin and destination are set
calculate();
}
});
map.data.loadGeoJson("http://www.geocodezip.com/directions.json.txt");
}
google.maps.event.addDomListener(window, 'load', initialize);