diff --git a/package-lock.json b/package-lock.json index 7241e19..79a07a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1512,9 +1512,9 @@ "dev": true }, "@mapbox/mapbox-gl-supported": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-2.0.1.tgz", - "integrity": "sha512-HP6XvfNIzfoMVfyGjBckjiAOQK9WfX0ywdLubuPMPv+Vqf5fj0uCbgBQYpiqcWZT6cbyyRnTSXDheT1ugvF6UQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-3.0.0.tgz", + "integrity": "sha512-2XghOwu16ZwPJLOFVuIOaLbN0iKMn867evzXFyf0P22dqugezfJwLmdanAgU25ITvz1TvOfVP4jsDImlDJzcWg==", "dev": true }, "@mapbox/point-geometry": { @@ -5848,6 +5848,12 @@ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -5979,14 +5985,14 @@ "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==" }, "mapbox-gl": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-3.0.1.tgz", - "integrity": "sha512-o7C6sAlj6Hkdd4xQVEgQflgJYNYyZOAtYahhIOb9m8chI8umtWcCp8Ie0iGLYJvce1WHRMa3WGzs69ggwuWlDA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-3.2.0.tgz", + "integrity": "sha512-v8S7x+wTr35kJ9nqzgn/VPiSFZxBkyQhwCk9bdyiFHVwCukNGG3LXt03FoaHHTsOuB9JWenWE96k0Uw+HGMZ8w==", "dev": true, "requires": { "@mapbox/geojson-rewind": "^0.5.2", "@mapbox/jsonlint-lines-primitives": "^2.0.2", - "@mapbox/mapbox-gl-supported": "^2.0.1", + "@mapbox/mapbox-gl-supported": "^3.0.0", "@mapbox/point-geometry": "^0.1.0", "@mapbox/tiny-sdf": "^2.0.6", "@mapbox/unitbezier": "^0.0.1", @@ -5999,13 +6005,16 @@ "gl-matrix": "^3.4.3", "grid-index": "^1.1.0", "kdbush": "^4.0.1", + "lodash.clonedeep": "^4.5.0", "murmurhash-js": "^1.0.0", "pbf": "^3.2.1", "potpack": "^2.0.0", "quickselect": "^2.0.0", "rw": "^1.3.3", + "serialize-to-js": "^3.1.2", "supercluster": "^8.0.0", "tinyqueue": "^2.0.3", + "tweakpane": "^4.0.3", "vt-pbf": "^3.1.3" } }, @@ -8187,6 +8196,12 @@ "randombytes": "^2.1.0" } }, + "serialize-to-js": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/serialize-to-js/-/serialize-to-js-3.1.2.tgz", + "integrity": "sha512-owllqNuDDEimQat7EPG0tH7JjO090xKNzUtYz6X+Sk2BXDnOCilDdNLwjWeFywG9xkJul1ULvtUQa9O4pUaY0w==", + "dev": true + }, "serve-static": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", @@ -9237,6 +9252,12 @@ "resolved": "https://registry.npmjs.org/turf-meta/-/turf-meta-1.0.2.tgz", "integrity": "sha1-dNTElZOOskdypwsxoVfuPU/Wuhs=" }, + "tweakpane": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/tweakpane/-/tweakpane-4.0.3.tgz", + "integrity": "sha512-BlcWOAe8oe4c+k9pmLBARGdWB6MVZMszayekkixQXTgkxTaYoTUpHpwVEp+3HkoamZkomodpbBf0CkguIHTgLg==", + "dev": true + }, "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", diff --git a/package.json b/package.json index f8fcf8b..46d62da 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "insert-css": "^2.0.0", "json-loader": "^0.5.7", "lodash.once": "^4.0.0", - "mapbox-gl": "^3.0.1", + "mapbox-gl": "^3.2.0", "smokestack": "^3.6.0", "tap-status": "^1.0.1", "tape": "^4.6.0", diff --git a/src/directions.js b/src/directions.js index 9c7b769..9c03eab 100644 --- a/src/directions.js +++ b/src/directions.js @@ -54,7 +54,10 @@ import Instructions from './controls/instructions'; */ export default class MapboxDirections { + constructor(options) { + this._directions = null; + this._stateSnapshot = null; this._store = this._initStore(); this.actions = bindActionCreators(actions, this._store.dispatch); @@ -122,6 +125,7 @@ export default class MapboxDirections { }); if (map.getSource('directions')) map.removeSource('directions'); + if (map.getSource('directions:markers')) map.removeSource('directions:markers'); this._map = null; return this; @@ -143,6 +147,7 @@ export default class MapboxDirections { // Add and set data theme layer/style this._map.addSource('directions', geojson); + this._map.addSource('directions:markers', geojson); // Add direction specific styles to the map if (styles && styles.length) styles.forEach((style) => this._map.addLayer(style)); @@ -162,25 +167,59 @@ export default class MapboxDirections { } } + _areMarkersChangedOnly(state) { + const changedSubscriptionFields = []; + + if (!this._stateSnapshot) { + return false; + } + + MapboxDirections.SUBSCRIPTION_FIELDS.forEach(field => { + if (this._stateSnapshot[field] !== state[field]) { + changedSubscriptionFields.push(field); + } + }); + + return changedSubscriptionFields.length <= MapboxDirections.MARKER_FIELDS.length && changedSubscriptionFields.every(field => { + return MapboxDirections.MARKER_FIELDS.includes(field); + }); + } + subscribedActions() { this.storeUnsubscribe = this._store.subscribe(() => { + const state = this._store.getState(); const { origin, destination, hoverMarker, directions, routeIndex - } = this._store.getState(); + } = state; - const geojson = { + const markersChangedOnly = this._areMarkersChangedOnly(state); + + this._stateSnapshot = state; + + const markersGeojson = { type: 'FeatureCollection', features: [ origin, destination, hoverMarker - ].filter((d) => { - return d.geometry; - }) + ].filter(d => d.geometry) + } + + if (this._map.style && this._map.getSource('directions:markers')) { + this._map.getSource('directions:markers').setData(markersGeojson); + } + + if (markersChangedOnly) { + return; + } + + const geojson = { + type: 'FeatureCollection', + features: [] }; if (directions.length) { @@ -570,3 +609,6 @@ export default class MapboxDirections { return this; } } + +MapboxDirections.MARKER_FIELDS = ['origin', 'destination', 'hoverMarker']; +MapboxDirections.SUBSCRIPTION_FIELDS = ['origin', 'destination', 'hovedMarker', 'directions', 'routeIndex']; \ No newline at end of file diff --git a/src/directions_style.js b/src/directions_style.js index 2275c2f..87ee5ba 100644 --- a/src/directions_style.js +++ b/src/directions_style.js @@ -63,7 +63,7 @@ const style = [{ }, { 'id': 'directions-hover-point-casing', 'type': 'circle', - 'source': 'directions', + 'source': 'directions:markers', 'paint': { 'circle-radius': 8, 'circle-color': '#fff' @@ -76,7 +76,7 @@ const style = [{ }, { 'id': 'directions-hover-point', 'type': 'circle', - 'source': 'directions', + 'source': 'directions:markers', 'paint': { 'circle-radius': 6, 'circle-color': '#3bb2d0' @@ -89,7 +89,7 @@ const style = [{ }, { 'id': 'directions-waypoint-point-casing', 'type': 'circle', - 'source': 'directions', + 'source': 'directions:markers', 'paint': { 'circle-radius': 8, 'circle-color': '#fff' @@ -102,7 +102,7 @@ const style = [{ }, { 'id': 'directions-waypoint-point', 'type': 'circle', - 'source': 'directions', + 'source': 'directions:markers', 'paint': { 'circle-radius': 6, 'circle-color': '#8a8bc9' @@ -115,7 +115,7 @@ const style = [{ }, { 'id': 'directions-origin-point', 'type': 'circle', - 'source': 'directions', + 'source': 'directions:markers', 'paint': { 'circle-radius': 18, 'circle-color': '#3bb2d0' @@ -128,7 +128,7 @@ const style = [{ }, { 'id': 'directions-origin-label', 'type': 'symbol', - 'source': 'directions', + 'source': 'directions:markers', 'layout': { 'text-field': 'A', 'text-font': ['Open Sans Bold', 'Arial Unicode MS Bold'], @@ -145,7 +145,7 @@ const style = [{ }, { 'id': 'directions-destination-point', 'type': 'circle', - 'source': 'directions', + 'source': 'directions:markers', 'paint': { 'circle-radius': 18, 'circle-color': '#8a8bc9' @@ -158,7 +158,7 @@ const style = [{ }, { 'id': 'directions-destination-label', 'type': 'symbol', - 'source': 'directions', + 'source': 'directions:markers', 'layout': { 'text-field': 'B', 'text-font': ['Open Sans Bold', 'Arial Unicode MS Bold'], diff --git a/test/test.directions.js b/test/test.directions.js index 66f9ac9..8832a6f 100644 --- a/test/test.directions.js +++ b/test/test.directions.js @@ -84,8 +84,10 @@ test('Directions#onRemove', t => { map.on('load', () => { directions.on('route', once(()=>{ t.true(!!map.getSource('directions'), 'directions source is added'); + t.true(!!map.getSource('directions:markers'), 'directions markers source is added'); map.removeControl(directions); t.false(!!map.getSource('directions'), 'directions source is removed'); + t.false(!!map.getSource('directions:markers'), 'directions markers source is removed'); t.end(); })); directions.setOrigin('Queen Street NY');