-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
add symbol-sort-key
style property
#7678
Conversation
This property allows users to specify a sorting order for symbols. Symbols are sorted in ascending order based on the key. Symbols with lower keys will appear below symbols with higher keys when they are rendered with overlap. Symbols with lower keys will be placed before symbols with higher keys. This also fixes #7111 by defining a sort order across tile boundaries.
Tagging @kkaefer because he opened the initial proposal in #4361. This implementation adds sorting as a layout property instead of a top level property because adding layout properties seems easier. This also uses a key instead of a comparator because while it is less powerful it is a bit simpler with expressions and a bit more optimizable. |
src/render/draw_symbol.js
Outdated
painter.transform.zoom, buffers.programConfigurations.get(layer.id), | ||
buffers.dynamicLayoutVertexBuffer, buffers.opacityVertexBuffer); | ||
} | ||
|
||
function drawSymbolsSorted(painter: Painter, renderData: Array<SymbolTileRenderState>, layer, colorMode, stencilMode) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we refactor this so it's "prepare draw state per tile, then draw once per segment" whether we're sorting or not? I think it would be easier to follow that way -- we wouldn't have to deal with the ambiguous naming that drawLayerSymbols
is sometimes a preparation step and sometimes an actual draw step.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think my thinking here was to avoid the extra overhead for symbol layers that don't need this but I should probably benchmark to see if this is valid. It looks like it should be pretty cheap to do what you are suggesting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ChrisLoer I've pushed a commit to always use the preparation step. Can you review?
We could add a
We could use an expression like |
We decided that we should leave this out and add it later if it seems useful.
We decided to use keys for simplicity. If we need to support tie breaking later one we can try to add arrays of keys. |
/cc @mapbox/studio |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes LGTM. I can see this being worthwhile to account for in Studio. Especially for custom data where features may not be sorted correctly.
The original issue brought up supporting this for circle types. Curious what the timing is for that along with other layer types like line, fill?
LGTM! But let's add at least one render test that exercises sorting at a tile boundary? |
@ChrisLoer thanks for catching that, I forgot to commit them. The render tests test sorting at boundaries for text, icons and for text, and with placement enabled. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
This answer is kinda hard to answer though since the hierarchy is reverse for the two styling options (overlapping or not). I could see use cases for both ascending and descending, but this seems reasonable if we have to pick one.
|
Could symbol-sort-key also work for text overlap? It currently only seems to work for icon overlap ('icon-allow-overlap':false). The idea could be extended to be text overlap for the following style:
|
This was an unfortunate decision for us. We have a symbol layer rendering location names, and a circle layer rendering their points. The source is the same for both, and is sorted in descending order by our own concept of location "importance". The top labels are rendered first, and preclude others that follow due to collision. However, the circle layer renders the least important points last, which means they occlude the more important points. This matters for us since our circles are color-coded (low importance locations are usually grey). Our case would be solved by introducing More ideal would be adding another option to It seems like either suggestion above shouldn't be too bad implement, though I can't say with certainty without knowing the codebase. Would it be possible to introduce one of the features above, or any other option that would solve this use case? |
@aMoniker sorry, I missed this comment earlier. Would it be possible for you to add a property in the data which you could use with |
@ansis No worries, I appreciate the reply. I suppose we could add a |
You could also use expression to invert the value |
This property allows users to specify a sorting order for symbols. Symbols are sorted in ascending order based on the key. Symbols with lower keys will appear below symbols with higher keys when they are rendered with overlap. Symbols with lower keys will be placed before symbols with higher keys.
This fixes #7111 by defining a sort order across tile boundaries.
This also adds an
auto
option forsymbol-z-order
which will be the new default. It does not change the behavior of the default value though.Launch Checklist
@mapbox/studio
and/or@mapbox/maps-design
if this PR includes style spec changesfeatures
With the following style you would render feature 2 above feature 1 above feature 0:
With the following style it would give feature 0 priority over other features if they collide:
@mapbox/studio @mapbox/maps-design
Sorting between layers is currently out of scope.