Reputation: 15
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 points and set them as Origin and destination.
Here's my code
google.maps.event.addListener(map.data, 'addfeature', function (e) {
if (e.feature.getGeometry().getType() === 'Point') {
map.setCenter(e.feature.getGeometry().get());
if (!origin) origin = e.feature.getGeometry().get(); //if origin does not exist
else if (!destination) {
destination = e.feature.getGeometry().get();
calculate();
}
}
});
Any idea ? Do I have to create a loop ? Or change the json code for the waypoints ?
Here's my json :
{
"type": "FeatureCollection",
"features":
[
{ "type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.562686, 45.4960413]},
"properties": {"prop0": "value0"}
},
{ "type": "Feature",
"geometry": {"type": "Point", "coordinates": [-73.568367, 45.4933086]},
"properties": {"prop0": "value0"}
}
]
}
Thanks !
Upvotes: 0
Views: 6837
Reputation: 161384
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.
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);
Upvotes: 1
Reputation: 117354
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/
Upvotes: 0