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

Set the feature state for all features in a source #9709

Open
itko opened this issue May 20, 2020 · 7 comments
Open

Set the feature state for all features in a source #9709

itko opened this issue May 20, 2020 · 7 comments

Comments

@itko
Copy link

itko commented May 20, 2020

Motivation

Sometimes, it is necessary to change the state of all features at once. As an example, let's take a layer with circle elements. We would like to create an effect where clicking on one of the circles will change the color of all the other circles (except for the one that is clicked).

Currently, there are two ways to accomplish this:

  1. Create two layers with different colors and use filters which are triggered by click events. This can be tricky when dealing with click events.
  2. Use queryRenderedFeatures and then loop through each feature in order to set its state. This is incomplete, because queryRenderedFeatures does not retrieve all features.

If one could change all states at once, then a user could use that in order to recolor all circles, and then change the state of the circle that was clicked in order to return that circle to its previous state.

Design Alternatives

Make the id argument optional for setFeatureState(), just like removeFeatureState(). When the id argument is excluded, setFeatureState() would be applied to the entire layer.

@andrewharvey andrewharvey changed the title Set the feature state for all features in a layer Set the feature state for all features in a source May 21, 2020
@andrewharvey
Copy link
Collaborator

I've tweaked your title, hope that's okay, because feature states apply at the source level not the layer level (eg. if you have two layers using one source).

@itko
Copy link
Author

itko commented May 22, 2020

Very true. Thanks!

@asheemmamoowala
Copy link
Contributor

We would like to create an effect where clicking on one of the circles will change the color of all the other circles (except for the one that is clicked).

@itko Have you tried doing this with a single layer and a configuration where the paint property expression is updated to change the color for all circles and uses feature-state only for the color of the selected circle? Additional states of circles can also be managed with appropriate feature-state values.

@itko
Copy link
Author

itko commented May 27, 2020

@asheemmamoowala Good point. Using setPaintProperty, I can get the desired functionality by doing the following:

  • On click: set the paint property to some default value.
  • On clicking the circles: set the paint property to a feature-state expression, remove all states, and then set the state of the clicked feature

This solution is a little less clean than setting all the feature-states in a source, but considering how niche this use case is, maybe setPaintProperty is good enough?

For what it's worth, I've noticed a slight delay with setPaintProperty which I don't notice with state-based properties.

@asheemmamoowala
Copy link
Contributor

#7122 would result in quite a performance hitting when using source/source-layer wide state values.

how niche this use case is, maybe setPaintProperty is good enough?

Thinking about this further, the use case described here would be well served by global state variables in expressions, discussed in #7946.

@stevage
Copy link
Contributor

stevage commented Jun 22, 2020

I was also just thinking that if this is easier to implement, it could be a workaround for the lack of configurable global state. :)

@rhysstubbs
Copy link

@itko The usecase you described is similar to something I am doing currently. As far as I am aware it is currently not possible to load a source with feature state already set, right?

Perhaps there is a something I am missing...

My current style expression uses feature-state to change the colour of layers.

I have a scenario whereby multiple sources are loaded, 2 layers are added for each, I need to set the feature-state for all features in a particular source. I can use querySourceFeatures but that does not gurantee to return me all features as they are still loading, I could use queryRenderedFeatures but again this does not gurantee to return all features.

My current solution is using querySourceFeatures but this is flawed because there is not a way for me to know when all features have loaded, is there? Responding to user interaction with either of those methods works perfectly because all the sources/features are loaded by then, as for my scenario the perfect solution would be to be able to add a source with feature-state already set in the GeoJson as I'd know server-side what is required.

Any advice would be appreciated :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants