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

queryRenderedFeatures doesn't use actual rendered font glyph #6621

Closed
hyperknot opened this issue May 5, 2018 · 4 comments
Closed

queryRenderedFeatures doesn't use actual rendered font glyph #6621

hyperknot opened this issue May 5, 2018 · 4 comments

Comments

@hyperknot
Copy link

hyperknot commented May 5, 2018

mapbox-gl-js version: 0.44.2
browser: Chrome 66 / macOS

Steps to Trigger Behavior

This functionality breaks using font-icons for custom markers.

  1. Use a big text-size (demonstration uses crazy 200, but this is very visible at 30+)
  2. Display a glyph
  3. queryRenderedFeatures will trigger for a region which can either be much bigger or much smaller compared to the actual rendered pixels.

Link to Demonstration

https://codesandbox.io/s/2w13wxzyrp
Try different zoom levels and move the mouse around. Sometimes it triggers even in Europe, sometimes it doesn't trigger even when over the text.

monosnap 2018-05-06 10-35-10

Expected Behavior

queryRenderedFeatures should check for actual rendered feature on a given pixel.

Actual Behavior

queryRenderedFeatures is triggered for a rectangular region, which is very different from the actual rendered glyph.

@ChrisLoer
Copy link
Contributor

Hi @hyperknot it looks like you've already figured out the underlying behavior, but just for clarity -- you can see the query range for symbols by setting map.showCollisionBoxes = true. So for your map:

screenshot 2018-05-07 11 10 45

The behavior where your pointer is only showing up occasionally is because your icon is at "null island" and is split across four tiles, and the querying only works for one tile at time. That will actually be fixed in the imminent v.45 release: #5475 (comment).

Querying "actual rendered pixels" is not the way GL JS currently works (instead, we query the simplified geometry we use for collision detection). It's something we're actively thinking about improving, although it's hard to say what the exact right behavior should be (should the middle of an "o" be considered part of the symbol or not?).

cc @ansis

@hyperknot
Copy link
Author

hyperknot commented May 7, 2018

@ChrisLoer, thanks for the explanation and for showCollisionBoxes. Yes, 0.45 beta fixes the tiles issues, but my main issue remains.

Let me explain this in context, I'm migrating a huge codebase from Leaflet to Mapbox GL, and the main reason for doing so is to have the better performance when 1000+ custom markers are displayed. (one such example map is this one: https://maphub.net/BreastfeedingMap/map)

Having a DOM based marker support (like in Leaflet and Mapbox GL's Marker class) is seriously limiting once you get above a few hundred markers.

This means the only way to implement high performance custom markers in Mapbox GL is to use icon fonts (via fontnik/pbr) and display codepoint characters. It works wonderfully and is very high performance. 1000+ custom markers are a non-issue in terms of performance.

But this clicking detection is very limiting. When markers are overlapping it is a very bad user experience to use bounding boxes as usually this selects the wrong marker. It's actually so bad that I was considering using OpenLayers because of this limitation. Somehow OpenLayers is able to do this querying in a pixel precise way.

At the end, I created a circle layer with 0 opacity, just for picking markers. It works well, although being a circle it's not covering a marker precisely, but it's good enough and allows me to use Mapbox GL.

If you have any recommendation for this use case I'm open to hear that.

cc @ansis

monosnap 2018-05-07 21-34-10
monosnap 2018-05-07 21-34-36

@ChrisLoer
Copy link
Contributor

That's really useful context for us, thanks @hyperknot!

Using an invisible circle layer to mark the approximate bounds of the icon is a clever workaround, I don't think I have much to add to it.

For the overlapping marker case, we also just fixed #6184, so that the query results order should match the rendering order of overlapping icons. That might make the overlapping experience a little more predictable although fundamentally the issue remains that the "collision box" for the frontmost marker could occlude a marker behind it, even if the actual pixels of the frontmost marker didn't occlude the rear marker.

@hyperknot
Copy link
Author

hyperknot commented May 7, 2018

Yes, that's exactly the case! Collision-box vs. non-rectangular overlapping markers are the core of the issue.

It seems I'm not the only user who is having the exact same problem, hopefully this will be implemented in a future version. For my use case (and I believe for most users) a simple convex-hull like shape would be fine, there is no need to have a hole in the O. Also, if this affects performance, maybe it can be an optional layout switch.

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

No branches or pull requests

2 participants