Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove the flickering effect when clicking on features #1321

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
5 changes: 1 addition & 4 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
8 changes: 4 additions & 4 deletions src/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
});
});
}
Expand All @@ -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;
}
40 changes: 11 additions & 29 deletions src/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
19 changes: 3 additions & 16 deletions src/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: []
Expand All @@ -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);
}
}
};
Expand Down
5 changes: 1 addition & 4 deletions src/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 1 addition & 10 deletions test/features_at.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: [{
Expand Down
Loading
Loading