Skip to content

Commit eb6cf3c

Browse files
author
Nicolas Marien
committed
Merge branch 'waypoint-index'
See mapbox#200 Thanks to @patrix for the fix
2 parents 899e97c + 38de4cf commit eb6cf3c

File tree

6 files changed

+140
-13
lines changed

6 files changed

+140
-13
lines changed

API.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
- [getWaypoints](#getwaypoints)
1717
- [removeRoutes](#removeroutes)
1818
- [on](#on)
19+
- [off](#off)
1920

2021
## MapboxDirections
2122

@@ -173,13 +174,43 @@ Subscribe to events that happen within the plugin.
173174

174175
**Parameters**
175176

177+
<<<<<<< HEAD
178+
176179
- `type` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** name of event. Available events and the data passed into their respective event objects are:- **clear** `{ type: } Type is one of 'origin' or 'destination'`
177180
- **loading** `{ type: } Type is one of 'origin' or 'destination'`
178181
- **profile** `{ profile } Profile is one of 'driving', 'walking', or 'cycling'`
179182
- **origin** `{ feature } Fired when origin is set`
180183
- **destination** `{ feature } Fired when destination is set`
181184
- **route** `{ route } Fired when a route is updated`
182185
- **error** \`{ error } Error as string
183-
- `fn` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** function that's called when the event is emitted.
186+
- # `fn` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** function that's called when the event is emitted.
187+
- `type` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** name of event. Available events and the data passed into their respective event objects are:
188+
- **clear** `{ type: } Type is one of 'origin' or 'destination'`
189+
- **loading** `{ type: } Type is one of 'origin' or 'destination'`
190+
- **profile** `{ profile } Profile is one of 'driving', 'walking', or 'cycling'`
191+
- **origin** `{ feature } Fired when origin is set`
192+
- **destination** `{ feature } Fired when destination is set`
193+
- **route** `{ route } Fired when a route is updated`
194+
- **error** \`{ error } Error as string
195+
- `fn` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** function that's called when the event is emitted.
196+
> > > > > > > waypoint-index
197+
198+
Returns **[MapboxDirections](#mapboxdirections)** this;
199+
200+
### off
201+
202+
Unsubscribe to events previously registered.
203+
204+
**Parameters**
205+
206+
- `type` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** name of event. Available events and the data passed into their respective event objects are:
207+
- **clear** `{ type: } Type is one of 'origin' or 'destination'`
208+
- **loading** `{ type: } Type is one of 'origin' or 'destination'`
209+
- **profile** `{ profile } Profile is one of 'driving', 'walking', or 'cycling'`
210+
- **origin** `{ feature } Fired when origin is set`
211+
- **destination** `{ feature } Fired when destination is set`
212+
- **route** `{ route } Fired when a route is updated`
213+
- **error** \`{ error } Error as string
214+
- `fn` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** function used when the event was registered.
184215

185216
Returns **[MapboxDirections](#mapboxdirections)** this;

src/actions/index.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,34 @@ export function eventSubscribe(type, fn) {
343343
};
344344
}
345345

346+
export function eventUnsubscribe(type, fn) {
347+
return (dispatch, getState) => {
348+
const { events } = getState();
349+
350+
if (!events[type]) {
351+
return {
352+
type: types.EVENTS,
353+
events
354+
};
355+
}
356+
357+
if (fn) {
358+
// Drop the event if it exists in the events object
359+
const fnToDelete = events[type].indexOf(fn);
360+
if (fnToDelete >= 0) {
361+
events[type].splice(fnToDelete, 1);
362+
}
363+
} else {
364+
delete events[type];
365+
}
366+
367+
return {
368+
type: types.EVENTS,
369+
events: events
370+
};
371+
};
372+
}
373+
346374
export function eventEmit(type, data) {
347375
return (dispatch, getState) => {
348376
const { events } = getState();

src/controls/inputs.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,18 @@ export default class Inputs {
3636
}
3737

3838
animateToCoordinates(mode, coords) {
39-
const { origin, destination } = this.store.getState();
39+
const { origin, destination, waypoints } = this.store.getState();
4040

4141
if (origin.geometry &&
4242
destination.geometry &&
4343
!isEqual(origin.geometry, destination.geometry)) {
4444

45+
const ways = waypoints.filter((waypoint) => (waypoint.geometry))
46+
4547
// Animate map to fit bounds.
4648
const bb = extent({
4749
type: 'FeatureCollection',
48-
features: [origin, destination]
50+
features: [origin, destination, ...ways]
4951
});
5052

5153
this._map.fitBounds([[bb[0], bb[1]], [bb[2], bb[3]]], { padding: 80 });

src/controls/instructions.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export default class Instructions {
3838

3939
if (directions.length && shouldRender) {
4040
const direction = this.directions = directions[routeIndex];
41+
const allSteps = direction.legs.reduce((legs, leg) => legs.concat(leg.steps), []);
4142

4243
if (compile) {
4344
direction.legs.forEach(function(leg) {
@@ -50,7 +51,7 @@ export default class Instructions {
5051
this.container.innerHTML = instructionsTemplate({
5152
routeIndex,
5253
routes: directions.length,
53-
steps: direction.legs[0].steps, // Todo: Respect all legs,
54+
steps: allSteps,
5455
format: utils.format[unit],
5556
duration: utils.format[unit](direction.distance),
5657
distance: utils.format.duration(direction.duration)

src/directions.js

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,9 @@ export default class MapboxDirections {
108108
* @returns {Control} `this`
109109
*/
110110
onRemove(map) {
111-
this.container.parentNode.removeChild(this.container);
111+
if (this.container.parentNode !== null) {
112+
this.container.parentNode.removeChild(this.container);
113+
}
112114
this.removeRoutes();
113115
map.off('mousedown', this.onDragDown);
114116
map.off('mousemove', this.move);
@@ -313,7 +315,6 @@ export default class MapboxDirections {
313315
}
314316
} else {
315317
this.actions.setDestinationFromCoordinates(coords);
316-
this._map.flyTo({ center: coords });
317318
}
318319
}
319320
}
@@ -383,7 +384,7 @@ export default class MapboxDirections {
383384
_onDragUp() {
384385
if (!this.isDragging) return;
385386

386-
const { hoverMarker, origin, destination } = store.getState();
387+
const { hoverMarker, origin, destination, waypoints } = store.getState();
387388

388389
switch (this.isDragging.layer.id) {
389390
case 'directions-origin-point':
@@ -396,11 +397,10 @@ export default class MapboxDirections {
396397
break;
397398
case 'directions-hover-point':
398399
// Add waypoint if a sufficent amount of dragging has occurred.
399-
if (
400-
hoverMarker.geometry &&
401-
!utils.coordinateMatch(this.isDragging, hoverMarker)
402-
) {
403-
this.actions.addWaypoint(0, hoverMarker);
400+
if (hoverMarker.geometry && !utils.coordinateMatch(this.isDragging, hoverMarker)) {
401+
const click = this.isDragging.geometry.coordinates;
402+
const index = utils.getNextWaypoint(this.getRoute.bind(this), waypoints, click);
403+
this.actions.addWaypoint(index, hoverMarker);
404404
}
405405
break;
406406
}
@@ -548,6 +548,21 @@ export default class MapboxDirections {
548548
return store.getState().waypoints;
549549
}
550550

551+
/**
552+
* Fetch all current points in a route.
553+
* @returns {Array} route points
554+
*/
555+
getRoute() {
556+
return this
557+
._map
558+
.getSource('directions')
559+
._data
560+
.features
561+
.find(({geometry}) => geometry.type === 'LineString')
562+
.geometry
563+
.coordinates;
564+
}
565+
551566
/**
552567
* Removes all routes and waypoints from the map.
553568
*
@@ -577,4 +592,15 @@ export default class MapboxDirections {
577592
this.actions.eventSubscribe(type, fn);
578593
return this;
579594
}
595+
596+
/**
597+
* Unsubscribe to events
598+
* @param {String} type name of event. Available events are outlined in `on`
599+
* @param {Function} fn optional. The function that's called when the event is emitted.
600+
* @returns {Directions} this;
601+
*/
602+
off(type, fn) {
603+
this.actions.eventUnsubscribe(type, fn);
604+
return this;
605+
}
580606
}

src/utils.js

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,43 @@ const format = {
6262
}
6363
};
6464

65-
export default { format, coordinateMatch, createPoint, validCoords, wrap, roundWithOriginalPrecision };
65+
const distance = ([x1, y1], [x2, y2]) =>
66+
Math.hypot((x1 - x2), (y1 - y2));
67+
68+
const nearest = origin =>
69+
(p1, p2, index) =>
70+
(distance(origin, p1) < distance(origin, p2))
71+
? p1
72+
: p2.concat(index);
73+
74+
75+
const find = (route, origin) => route
76+
.reduce(nearest(origin), [Infinity, Infinity, -1])[2];
77+
78+
const compare = point =>
79+
waypoint =>
80+
coordinateMatch(point, waypoint);
81+
82+
const getNextWaypoint = (getRoute, waypoints, origin) => {
83+
if (waypoints.length === 0) return 0;
84+
85+
const route = getRoute();
86+
87+
for(let i = find(route, origin); i < route.length; i++) {
88+
const index = waypoints.findIndex(compare({ geometry: { coordinates: route[i] } }));
89+
if (index !== -1) {
90+
return index;
91+
}
92+
}
93+
return waypoints.length;
94+
};
95+
96+
export default {
97+
format,
98+
coordinateMatch,
99+
createPoint,
100+
validCoords,
101+
wrap,
102+
roundWithOriginalPrecision,
103+
getNextWaypoint
104+
};

0 commit comments

Comments
 (0)