-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Highlight features spread across tiles #4365
Highlight features spread across tiles #4365
Conversation
I think one fix that needs to happen is in GeoJsonLayer - |
Hi @Pessimistress will that fix be available for the next 8.1.0 release? |
We are releasing soon - the fix will land as a patch. |
Great, ping us if you need any help or review on that! |
@jesusbotella Landed #4403, this PR should have been unblocked. |
Thank you @Pessimistress! That was fast! I have just tested my code after the merge and it works but I have some problems with particular polygons. Here's a GIF: Particularly with the top big polygon, it works to highlight most of it but there's a part that remains unhighlighted. I've uploaded the example that I'm using so that you can see what happens. Some features are successfully highlighted but others don't. I need to tweak the code a bit so that features stop being highlighted, but that'll come later. Thank you! |
@@ -9,6 +9,11 @@ import ClipExtension from './clip-extension'; | |||
|
|||
const WORLD_SIZE = 512; | |||
|
|||
const defaultProps = { | |||
...TileLayer.defaultProps, |
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.
defaultProps
of the base class is automatically merged.
I've pushed commits to make it work properly with @Pessimistress changes. First of all, I've tweaked the code to unhighlight features when mouse is moved off the feature. Another important thing is that I've changed MVT custom highlighting to only work when And I noticed that this change broke Let me know what you think, and if you like it, I'll add docs and tests. |
@AdriSolid That "partial highlighting" should be fixed when this PR gets merged. Regarding to that, @Pessimistress do you think that we should go on and create docs & tests for it with the current approach for unhighlighting? |
Hey @Pessimistress! I have just set this PR as ready for review. It would be great if you (or any other contributor) could give it a look and tell us your thoughts. Thank you very much! |
@@ -20,7 +20,8 @@ const defaultProps = { | |||
maxCacheSize: null, | |||
maxCacheByteSize: null, | |||
refinementStrategy: STRATEGY_DEFAULT, | |||
zRange: null | |||
zRange: null, | |||
getHighlightedObjectIndex: {type: 'function', value: () => -1, compare: false} |
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 is not documented.
If this is going to be a public API, we need to look into whether it's sufficient to just pass it the tile
argument.
I think it's ok to not expose this until we find other use cases.
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.
Yeah, makes sense. Let's remove it and wait until we find some other use cases.
const hasFeatureId = Boolean(feature.id); | ||
const hasUniquePropertyId = Boolean(uniquePropertyId); | ||
|
||
if (hasFeatureId) { |
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'd expect the user-specified hasUniquePropertyId
to override the default
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.
Sure, makes more sense. I have just changed it.
I have just changed the suggestions mentioned in the review. I have also had to remove the interaction test because it was fragile. I guess that I have not been able to guess a proper wait time for firing the hover events and the property checking. I don't know if you have some ideas to make it work (besides increasing timeout). |
Hi @Pessimistress! Sorry for disturbing, I performed the review changes, and I would like some validation whenever you can. Thank you! |
docs/layers/mvt-layer.md
Outdated
|
||
An string pointing to a tile attribute containing a unique identifier for features across tiles. | ||
|
||
##### `highlightedFeatureId` (Number) |
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.
Does the feature id have to be a number? Is string accepted? If so, the default should be null
for clarity?
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.
As per MVT docs, feature ID can be only a number. But it's true that if anyone uses uniqueIdProperty
to reference an ID within feature properties, it could be a string.
I have just changed it to support strings as well in the code. Let me know if you see something weird.
Co-authored-by: Xiaoji Chen <Pessimistress@users.noreply.github.com>
I see that coverage has decreased. I tried to make a module test for highlighting to improve it, but I don't know how to make it pass because fetch is not supported in Node and the only way for MVT Layer to load data is through a URL. |
I am not up-to-date on the test setup in deck.gl, but the |
Thank you @ibgreen! I tried modifying this file (https://github.com/visgl/deck.gl/blob/master/test/modules/geo-layers/mvt-layer.spec.js) but I believe that the output already prints a |
I kinda found a fix for those errors, that is checking if our template value type has a replace method. That way we avoid passing unwanted values like About fetch, there is this line in Node tests setup: Lines 3 to 5 in 583cde5
It seems difficult for me to test highlighting without tile data, so I don't know if you have a clue for me to inject that data into the layer and if you have some scheduled work to see why using |
@ibgreen @Pessimistress we're a bit stuck on this... any advice on how we could move on? |
@jesusbotella Since we are not testing the loader here, you can bypass the default loading routine with this: class TestMVTLayer extends MVTLayer {
getTileData(tile) {
// return parsed MVT data directly
}
} |
@VictorVelarde Apologies the issue is not clear to me, is it still a matter of the tests? The CI tests do seem to be passing... We could certainly get fetch working in Node tests similar to how it works in loaders.gl if @Pessimistress thinks that makes sense. You could also just disable your tests when running under Node.js and only do these tests in the browser. |
Loaders has a quite complex system to reroute URLs in both node and browser. I prefer not to add that extra layer of complexity if we don't have to. |
Thank you both for your comments! @ibgreen @Pessimistress There's no need to make fetch work with those tests. I think that it's better to override The PR is ready if we forget about coverage decrease, but not feeling happy about that 😓 The thing is that the method that I added in this PR ( The method needs the actual data to find the feature within the tile data array, but the tile data that I get when the method is called in the tests is a promise. I understand that it gets wrapped in a promise in case When using the layer in a normal environment, I'm relying on a layer re-render that triggers on every tile load to find the index, and here's not happening. So, I don't know what to do now, to be honest :( Here's the test that I did, and wanted to check highlightedObjectId within all sublayers, but I have not been able to do that: test('MVT Highlight', t => {
class TestMVTLayer extends MVTLayer {
getTileData() {
return geoJSONData;
}
}
const testCases = [
{
props: {
data: ['https://a.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}.png'],
id: 'mvt-highlight-test',
filled: true,
pickable: true,
autoHighlight: true,
highlightedFeatureId: 1
},
onAfterUpdate: ({ subLayers }) => {
for (const layer of subLayers) {
t.comment(layer.props.pickable);
t.comment(layer.props.autoHighlight);
t.comment(layer.props.highlightedObjectIndex);
t.comment(layer.props.highlightedFeatureId);
}
}
}
];
testLayer({ Layer: TestMVTLayer, testCases, onError: t.notOk });
t.end();
}); |
It's a long due backlog item to support asynchronous checks in FYI if you rebase master the coverage should go up. |
Oh, didn't know about that, but don't worry about fixing it for this. It sounds as a relief because I was kinda hitting my head against the wall 😁 Ok, so I am gonna commit it and skip that test. I'm not worried about this particular test because there's another one with a render image that works perfect, so we are good with this. |
Background
Right now, only one feature is highlighted when
autoHighlight
property is enabled and the feature is split into several tiles. We would need to highlight the whole feature instead of only the hovered part.I misunderstood the object index and returned the index within the provided data array instead of the picking index. Is there a way to get the picking index from a given property?
Change List
highlightedObjectIndex
to rendered sublayers inTileLayer
.getHighlightedObjectIndex
inMVTTileLayer
.hoveredFeatureId
intoMVTTileLayer
state.