diff --git a/docs/API.md b/docs/API.md index 1010f0eda..987aa3164 100644 --- a/docs/API.md +++ b/docs/API.md @@ -526,15 +526,12 @@ Draw uses a map style that adheres to the [Mapbox GL Style Spec](https://www.map **source** -The GL Style Spec requires each layer to have a source. However, **do not provide a `source`** when styling Draw. - -Draw moves features between sources in order to fine-tune performance. Because of this, **Draw will provide a `source` for you automatically**. - -The `source`s that Draw provides are named `mapbox-gl-draw-hot` and `mapbox-gl-draw-cold`. +The GL Style Spec requires each layer to have a source. However, **do not provide a `source`** when styling Draw. **Draw will provide a `source` for you automatically**. +The `source` that Draw provides is named `mapbox-gl-draw`. **id** -The GL Style Spec also requires an id. **You must provide an id**. Draw will then add the suffixes `.hot` and `.cold` to your id. +The GL Style Spec also requires an id. **You must provide an id**. In your custom style, you will want to use the following feature properties: diff --git a/src/constants.js b/src/constants.js index 581e0e57f..7844af8c7 100644 --- a/src/constants.js +++ b/src/constants.js @@ -15,10 +15,7 @@ export const classes = { BOX_SELECT: 'mapbox-gl-draw_boxselect' }; -export const sources = { - HOT: 'mapbox-gl-draw-hot', - COLD: 'mapbox-gl-draw-cold' -}; +export const source = 'mapbox-gl-draw'; export const cursors = { ADD: 'add', diff --git a/src/options.js b/src/options.js index 8e88928e6..b387620a6 100644 --- a/src/options.js +++ b/src/options.js @@ -36,12 +36,12 @@ const hideControls = { uncombine_features: false }; -function addSources(styles, sourceBucket) { +function addSource(styles) { return styles.map((style) => { if (style.source) return style; return Object.assign({}, style, { - id: `${style.id}.${sourceBucket}`, - source: (sourceBucket === 'hot') ? Constants.sources.HOT : Constants.sources.COLD + id: style.id, + source: Constants.source }); }); } @@ -62,7 +62,7 @@ export default function(options = {}) { withDefaults = Object.assign({}, defaultOptions, withDefaults); // Layers with a shared source should be adjacent for performance reasons - withDefaults.styles = addSources(withDefaults.styles, 'cold').concat(addSources(withDefaults.styles, 'hot')); + withDefaults.styles = addSource(withDefaults.styles); return withDefaults; } diff --git a/src/render.js b/src/render.js index ae63efb03..87bb7dc2c 100644 --- a/src/render.js +++ b/src/render.js @@ -3,55 +3,37 @@ import * as Constants from './constants.js'; export default function render() { // eslint-disable-next-line no-invalid-this const store = this; - const mapExists = store.ctx.map && store.ctx.map.getSource(Constants.sources.HOT) !== undefined; + const mapExists = store.ctx.map && store.ctx.map.getSource(Constants.source) !== undefined; if (!mapExists) return cleanup(); const mode = store.ctx.events.currentModeName(); store.ctx.ui.queueMapClasses({ mode }); - let newHotIds = []; - let newColdIds = []; + const newIds = store.getAllIds(); - if (store.isDirty) { - newColdIds = store.getAllIds(); - } else { - newHotIds = store.getChangedIds().filter(id => store.get(id) !== undefined); - newColdIds = store.sources.hot.filter(geojson => geojson.properties.id && newHotIds.indexOf(geojson.properties.id) === -1 && store.get(geojson.properties.id) !== undefined).map(geojson => geojson.properties.id); - } - - store.sources.hot = []; - const lastColdCount = store.sources.cold.length; - store.sources.cold = store.isDirty ? [] : store.sources.cold.filter((geojson) => { - const id = geojson.properties.id || geojson.properties.parent; - return newHotIds.indexOf(id) === -1; - }); + const lastCount = store.source.length; + store.source = []; - const coldChanged = lastColdCount !== store.sources.cold.length || newColdIds.length > 0; - newHotIds.forEach(id => renderFeature(id, 'hot')); - newColdIds.forEach(id => renderFeature(id, 'cold')); + const changed = lastCount !== store.source.length || newIds.length > 0; + newIds.forEach(id => renderFeature(id)); - function renderFeature(id, source) { + function renderFeature(id) { const feature = store.get(id); const featureInternal = feature.internal(mode); store.ctx.events.currentModeRender(featureInternal, (geojson) => { geojson.properties.mode = mode; - store.sources[source].push(geojson); + store.source.push(geojson); }); } - if (coldChanged) { - store.ctx.map.getSource(Constants.sources.COLD).setData({ + if (changed) { + store.ctx.map.getSource(Constants.source).setData({ type: Constants.geojsonTypes.FEATURE_COLLECTION, - features: store.sources.cold + features: store.source }); } - store.ctx.map.getSource(Constants.sources.HOT).setData({ - type: Constants.geojsonTypes.FEATURE_COLLECTION, - features: store.sources.hot - }); - cleanup(); function cleanup() { diff --git a/src/setup.js b/src/setup.js index e1524db82..af28231ac 100644 --- a/src/setup.js +++ b/src/setup.js @@ -71,16 +71,7 @@ export default function(ctx) { }, addLayers() { // drawn features style - ctx.map.addSource(Constants.sources.COLD, { - data: { - type: Constants.geojsonTypes.FEATURE_COLLECTION, - features: [] - }, - type: 'geojson' - }); - - // hot features style - ctx.map.addSource(Constants.sources.HOT, { + ctx.map.addSource(Constants.source, { data: { type: Constants.geojsonTypes.FEATURE_COLLECTION, features: [] @@ -104,12 +95,8 @@ export default function(ctx) { } }); - if (ctx.map.getSource(Constants.sources.COLD)) { - ctx.map.removeSource(Constants.sources.COLD); - } - - if (ctx.map.getSource(Constants.sources.HOT)) { - ctx.map.removeSource(Constants.sources.HOT); + if (ctx.map.getSource(Constants.source)) { + ctx.map.removeSource(Constants.source); } } }; diff --git a/src/store.js b/src/store.js index ed163a74d..a591978d6 100644 --- a/src/store.js +++ b/src/store.js @@ -12,10 +12,7 @@ export default function Store(ctx) { this._emitSelectionChange = false; this._mapInitialConfig = {}; this.ctx = ctx; - this.sources = { - hot: [], - cold: [] - }; + this.source = []; // Deduplicate requests to render and tie them to animation frames. let renderRequest; diff --git a/test/features_at.test.js b/test/features_at.test.js index 1209425e5..5b258be96 100644 --- a/test/features_at.test.js +++ b/test/features_at.test.js @@ -10,16 +10,7 @@ import setupOptions from '../src/options.js'; */ function addLayers(ctx) { // drawn features style - ctx.map.addSource(Constants.sources.COLD, { - data: { - type: Constants.geojsonTypes.FEATURE_COLLECTION, - features: [] - }, - type: 'geojson' - }); - - // hot features style - ctx.map.addSource(Constants.sources.HOT, { + ctx.map.addSource(Constants.source, { data: { type: Constants.geojsonTypes.FEATURE_COLLECTION, features: [{ diff --git a/test/fixtures/style_with_sources.json b/test/fixtures/style_with_sources.json index 32e4e4c65..0c0ee22e5 100644 --- a/test/fixtures/style_with_sources.json +++ b/test/fixtures/style_with_sources.json @@ -1,48 +1,29 @@ [ { - "id": "gl-draw-polygon-fill.cold", + "id": "gl-draw-polygon-fill", "type": "fill", "filter": [ "all", - [ - "==", - "$type", - "Polygon" - ] + ["==", "$type", "Polygon"] ], "paint": { "fill-color": [ "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], + ["==", ["get", "active"], "true"], "#fbb03b", "#3bb2d0" ], "fill-opacity": 0.1 }, - "source": "mapbox-gl-draw-cold" + "source": "mapbox-gl-draw" }, { - "id": "gl-draw-lines.cold", + "id": "gl-draw-lines", "type": "line", "filter": [ "any", - [ - "==", - "$type", - "LineString" - ], - [ - "==", - "$type", - "Polygon" - ] + ["==", "$type", "LineString"], + ["==", "$type", "Polygon"] ], "layout": { "line-cap": "round", @@ -51,474 +32,114 @@ "paint": { "line-color": [ "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], + ["==", ["get", "active"], "true"], "#fbb03b", "#3bb2d0" ], "line-dasharray": [ "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], - [ - 0.2, - 2 - ], - [ - 2, - 0 - ] + ["==", ["get", "active"], "true"], + [0.2, 2], + [2, 0] ], "line-width": 2 }, - "source": "mapbox-gl-draw-cold" + "source": "mapbox-gl-draw" }, { - "id": "gl-draw-point-outer.cold", + "id": "gl-draw-point-outer", "type": "circle", "filter": [ "all", - [ - "==", - "$type", - "Point" - ], - [ - "==", - "meta", - "feature" - ] + ["==", "$type", "Point"], + ["==", "meta", "feature"] ], "paint": { "circle-radius": [ "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], + ["==", ["get", "active"], "true"], 7, 5 ], "circle-color": "#fff" }, - "source": "mapbox-gl-draw-cold" + "source": "mapbox-gl-draw" }, { - "id": "gl-draw-point-inner.cold", + "id": "gl-draw-point-inner", "type": "circle", "filter": [ "all", - [ - "==", - "$type", - "Point" - ], - [ - "==", - "meta", - "feature" - ] + ["==", "$type", "Point"], + ["==", "meta", "feature"] ], "paint": { "circle-radius": [ "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], + ["==", ["get", "active"], "true"], 5, 3 ], "circle-color": [ "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], + ["==", ["get", "active"], "true"], "#fbb03b", "#3bb2d0" ] }, - "source": "mapbox-gl-draw-cold" + "source": "mapbox-gl-draw" }, { - "id": "gl-draw-vertex-outer.cold", + "id": "gl-draw-vertex-outer", "type": "circle", "filter": [ "all", - [ - "==", - "$type", - "Point" - ], - [ - "==", - "meta", - "vertex" - ], - [ - "!=", - "mode", - "simple_select" - ] + ["==", "$type", "Point"], + ["==", "meta", "vertex"], + ["!=", "mode", "simple_select"] ], "paint": { "circle-radius": [ "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], + ["==", ["get", "active"], "true"], 7, 5 ], "circle-color": "#fff" }, - "source": "mapbox-gl-draw-cold" + "source": "mapbox-gl-draw" }, { - "id": "gl-draw-vertex-inner.cold", + "id": "gl-draw-vertex-inner", "type": "circle", "filter": [ "all", - [ - "==", - "$type", - "Point" - ], - [ - "==", - "meta", - "vertex" - ], - [ - "!=", - "mode", - "simple_select" - ] + ["==", "$type", "Point"], + ["==", "meta", "vertex"], + ["!=", "mode", "simple_select"] ], "paint": { "circle-radius": [ "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], + ["==", ["get", "active"], "true"], 5, 3 ], "circle-color": "#fbb03b" }, - "source": "mapbox-gl-draw-cold" + "source": "mapbox-gl-draw" }, { - "id": "gl-draw-midpoint.cold", + "id": "gl-draw-midpoint", "type": "circle", "filter": [ "all", - [ - "==", - "meta", - "midpoint" - ] - ], - "paint": { - "circle-radius": 3, - "circle-color": "#fbb03b" - }, - "source": "mapbox-gl-draw-cold" - }, - { - "id": "gl-draw-polygon-fill.hot", - "type": "fill", - "filter": [ - "all", - [ - "==", - "$type", - "Polygon" - ] - ], - "paint": { - "fill-color": [ - "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], - "#fbb03b", - "#3bb2d0" - ], - "fill-opacity": 0.1 - }, - "source": "mapbox-gl-draw-hot" - }, - { - "id": "gl-draw-lines.hot", - "type": "line", - "filter": [ - "any", - [ - "==", - "$type", - "LineString" - ], - [ - "==", - "$type", - "Polygon" - ] - ], - "layout": { - "line-cap": "round", - "line-join": "round" - }, - "paint": { - "line-color": [ - "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], - "#fbb03b", - "#3bb2d0" - ], - "line-dasharray": [ - "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], - [ - 0.2, - 2 - ], - [ - 2, - 0 - ] - ], - "line-width": 2 - }, - "source": "mapbox-gl-draw-hot" - }, - { - "id": "gl-draw-point-outer.hot", - "type": "circle", - "filter": [ - "all", - [ - "==", - "$type", - "Point" - ], - [ - "==", - "meta", - "feature" - ] - ], - "paint": { - "circle-radius": [ - "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], - 7, - 5 - ], - "circle-color": "#fff" - }, - "source": "mapbox-gl-draw-hot" - }, - { - "id": "gl-draw-point-inner.hot", - "type": "circle", - "filter": [ - "all", - [ - "==", - "$type", - "Point" - ], - [ - "==", - "meta", - "feature" - ] - ], - "paint": { - "circle-radius": [ - "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], - 5, - 3 - ], - "circle-color": [ - "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], - "#fbb03b", - "#3bb2d0" - ] - }, - "source": "mapbox-gl-draw-hot" - }, - { - "id": "gl-draw-vertex-outer.hot", - "type": "circle", - "filter": [ - "all", - [ - "==", - "$type", - "Point" - ], - [ - "==", - "meta", - "vertex" - ], - [ - "!=", - "mode", - "simple_select" - ] - ], - "paint": { - "circle-radius": [ - "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], - 7, - 5 - ], - "circle-color": "#fff" - }, - "source": "mapbox-gl-draw-hot" - }, - { - "id": "gl-draw-vertex-inner.hot", - "type": "circle", - "filter": [ - "all", - [ - "==", - "$type", - "Point" - ], - [ - "==", - "meta", - "vertex" - ], - [ - "!=", - "mode", - "simple_select" - ] - ], - "paint": { - "circle-radius": [ - "case", - [ - "==", - [ - "get", - "active" - ], - "true" - ], - 5, - 3 - ], - "circle-color": "#fbb03b" - }, - "source": "mapbox-gl-draw-hot" - }, - { - "id": "gl-draw-midpoint.hot", - "type": "circle", - "filter": [ - "all", - [ - "==", - "meta", - "midpoint" - ] + ["==", "meta", "midpoint"] ], "paint": { "circle-radius": 3, "circle-color": "#fbb03b" }, - "source": "mapbox-gl-draw-hot" + "source": "mapbox-gl-draw" } -] \ No newline at end of file +] diff --git a/test/options.test.js b/test/options.test.js index aa2569646..0f5ef13f6 100644 --- a/test/options.test.js +++ b/test/options.test.js @@ -192,8 +192,8 @@ test('Options test', async (t) => { const styles = [ { - 'id': 'custom-polygon.cold', - 'source': 'mapbox-gl-draw-cold', + 'id': 'custom-polygon', + 'source': 'mapbox-gl-draw', 'type': 'fill', 'filter': ['all', ['==', '$type', 'Polygon']], 'paint': { @@ -201,26 +201,8 @@ test('Options test', async (t) => { } }, { - 'id': 'custom-point.cold', - 'source': 'mapbox-gl-draw-cold', - 'type': 'circle', - 'filter': ['all', ['==', '$type', 'Point']], - 'paint': { - 'circle-color': '#fff' - } - }, - { - 'id': 'custom-polygon.hot', - 'source': 'mapbox-gl-draw-hot', - 'type': 'fill', - 'filter': ['all', ['==', '$type', 'Polygon']], - 'paint': { - 'fill-color': '#fff' - } - }, - { - 'id': 'custom-point.hot', - 'source': 'mapbox-gl-draw-hot', + 'id': 'custom-point', + 'source': 'mapbox-gl-draw', 'type': 'circle', 'filter': ['all', ['==', '$type', 'Point']], 'paint': { diff --git a/test/store.test.js b/test/store.test.js index 836f4ea28..238c9c186 100644 --- a/test/store.test.js +++ b/test/store.test.js @@ -32,10 +32,7 @@ test('Store constructor and public API', () => { const store = new Store(ctx); // instance members - assert.deepEqual(store.sources, { - hot: [], - cold: [] - }, 'exposes store.sources'); + assert.deepEqual(store.source, [], 'exposes store.sources'); assert.equal(store.ctx, ctx, 'exposes store.ctx'); assert.equal(store.ctx.map, map, 'exposes store.ctx.map'); assert.equal(store.isDirty, false, 'exposes store.isDirty');