-
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 circle to GeolocateControl showing accuracy of position #9181
Conversation
Related to #9177 @ryanhamley @mourner @andrewharvey could you all give some feedback and direction for where to take this. Would especially like tips on what kind of tests would be appropriate and how to get started on those. |
@mapbox/map-design-team this adds a transparent blue circle around the standard GeolocateControl marker. Currently using |
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.
Thanks for this PR @Meekohi it's looking very good. I've left a few comments. Not saying I'm right and you need to change it, just something to think about.
src/ui/control/geolocate_control.js
Outdated
@@ -78,6 +80,7 @@ let noTimeout = false; | |||
* @param {Object} [options.positionOptions={enableHighAccuracy: false, timeout: 6000}] A Geolocation API [PositionOptions](https://developer.mozilla.org/en-US/docs/Web/API/PositionOptions) object. | |||
* @param {Object} [options.fitBoundsOptions={maxZoom: 15}] A [`fitBounds`](#map#fitbounds) options object to use when the map is panned and zoomed to the user's location. The default is to use a `maxZoom` of 15 to limit how far the map will zoom in for very accurate locations. | |||
* @param {Object} [options.trackUserLocation=false] If `true` the Geolocate Control becomes a toggle button and when active the map will receive updates to the user's location as it changes. | |||
* @param {Object} [options.showAccuracyRadius=true] Show a transparent circle approximating the position accuracy as reported by `navigator.geolocation.watchPosition`. Set to `false` to disable. |
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.
How about "By default a transparent circle will be drawn around the user location indicating the accuracy of the user's location"? What do you think?
I don't think we need to mention watchPosition,
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.
Agreed that we don't need to explicitly mention watchPosition
in this description. I think it might be helpful to note that if trackUserLocation=true
, the accuracy will be refined over time.
The name showAccuracyRadius
seems odd to me. It's not really a "radius", right? It's more like an area of uncertainty. Also, not sure how you feel @andrewharvey but I think this should probably be false
by 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.
I see this as just an extension of the showUserLocation option, should we support showUserLocation=false but still showing this accuracy circle? I'm not sure...
I'm on the fence with the default. After all we introduced showUserLocation=true as the default which changed behaviour when people upgraded. While I can understand we should try to avoid to unexpected changes in behaviour for users upgrading, this change is mostly cosmetic and if you're already showing the user location dot would you ever not want to show this accuracy circle?
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 I think this is the core question -- are there use cases for disabling the circle entirely? I do think defaulting to it visible makes sense although it is a change. I added the flag anticipating someone might see the change and want to go back to the old behavior (especially if they have done something unusual like customized the dot icon or etc).
I do think there is some value in explaining "how is the size of this circle chosen" in the docs, but can leave it out if there's agreement it isn't needed.
We could name it something friendly: "circle-of-confusion" is common but a bit wordy... the radius shown specifically represents the 95% confidence level in the latitude/longitude.
Maybe in this context just showAccuracy
is sufficient?
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.
Updated to
By default a transparent circle will be drawn around the user location indicating the accuracy (95% confidence level) of the user's location. Set to
false
to disable.
for now.
_geolocateButton: HTMLButtonElement; | ||
_geolocationWatchID: number; | ||
_timeoutId: ?TimeoutID; | ||
_watchState: 'OFF' | 'ACTIVE_LOCK' | 'WAITING_ACTIVE' | 'ACTIVE_ERROR' | 'BACKGROUND' | 'BACKGROUND_ERROR'; | ||
_lastKnownPosition: any; | ||
_userLocationDotMarker: Marker; | ||
_accuracyCircleMarker: Marker; |
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.
Given both markers will always have the same location, do you think it would be better to combine this with the _userLocationDotMarker to have a single Marker? Still having it optional and still using two separate classes for styling.
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.
Personally I think the code will be more complicated trying to force both of these objects to use one Marker: that would introduce some container element that will need to be styled carefully to avoid breaking anything, some additional if/else
around the flag, and I'd be worried that might introduce some other breaking change related to code I'm not familiar with, whereas I'm pretty confident the current design should be independent. (Obvious caveat I've only been looking at this codebase for 2 days so... let me know ;D)
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 probably prefer a single Marker since their location is always going to be the same, but I can also see how two Markers is easier to implement and in some ways makes the code easier to manage (though single Marker also makes the Marker update code cleaner).
That said, I'm happy with either option.
src/ui/control/geolocate_control.js
Outdated
@@ -476,6 +498,28 @@ class GeolocateControl extends Evented { | |||
|
|||
export default GeolocateControl; | |||
|
|||
function getDistance(latlng1, latlng2) { |
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 don't think this needs to be addressed within this PR, but eventually we should eliminate the duplication between this and
mapbox-gl-js/src/ui/control/scale_control.js
Lines 124 to 137 in 74b1573
function getDistance(latlng1, latlng2) { | |
// Uses spherical law of cosines approximation. | |
const R = 6371000; | |
const rad = Math.PI / 180, | |
lat1 = latlng1.lat * rad, | |
lat2 = latlng2.lat * rad, | |
a = Math.sin(lat1) * Math.sin(lat2) + | |
Math.cos(lat1) * Math.cos(lat2) * Math.cos((latlng2.lng - latlng1.lng) * rad); | |
const maxMeters = R * Math.acos(Math.min(a, 1)); | |
return maxMeters; | |
} |
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 agreed it's a copy/paste job -- good spot to refactor these into some helpers in the future.
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.
We'll likely forget about it later so let's eliminate duplication now — I think the best place to put it is LngLat
distanceTo(lngLat)
method. This would follow the same convention as Leaflet.
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.
Opened a separate PR for this: #9202
Nevermind, adding a css transition causes a lag when zoom changes -- not worth the complexity to split it out and manually animate I don't think. |
|
Trying to run the benchmark suite obliterated my entire computer and forced a restart 🤣. It doesn't look to me like any benchmarks actually exercise the GeolocateControl, and adding one DOM element shouldn't have any significant impact to performance, so I'm going to take it off the checklist. |
In that checklist you can just add an entry:
This is the way to go over editing CHANGELOG directly because the merge conflicts would be a nightmare, so that get's updated when the release is done. |
I tested this out using Chrome DevTools Sensor option and cycling through different locations I notice that as the map smoothly zooms in the accuracy circle will smoothly grow in size as it should, but then near the end it starts to jump around. Is that something you noticed? |
Taking a step back I'm seeing the limitations of using a Marker element for this, even just manually zooming in and out results in jitter and panning the map around near the edge the circle it moves relative to the ground, which it shouldn't. Normally for large circle the drawing out the circle as a polygon results in a much better experience, however the user location dot was intentionally done as a Marker to avoid mutating the users Style so to be honest I'm not sure the best way forward. |
@andrewharvey huh interesting -- I'd been assuming any 'jumping' I saw was due to the actual reported accuracy changing (actually kind of amusing, moving the phone under my desk immediately decreases the accuracy by ~50% or so), but I can reproduce this with the sensors devtools (I didn't know about those!) and will investigate. |
Depending on the browser/OS you're using, this could be related to #8614 |
* LOD support for tile coverage
I've been swayed by your arguments that default state should be on. I'm agnostic on one or two markers. That's an implementation detail that could change in the future so I don't think it's a make or break decision. |
Hey all, procedural question -- |
@Meekohi we do squash and merge when the PR is merged to master which automatically rebases if possible. It's probably ok to hold off merging/rebasing manually unless you need to. If you do, |
Okay rebased, merged, and updated to use the new distance refactor.
|
@Meekohi looks like something went wrong with the rebase, the diff now has a lot of other changes, which makes it hard to see what this PR is actually changing, could this be cleaned up? If you're not sure, maybe best to take a backup of your repo first just in case. |
🙄This is why I thought it's very strange this repo recommends rebasing instead of merging and asked about it. Github shows "three dot diffs" not "two dot diffs" -- I'll just start a new PR. |
I'm interested if there's anything you think could be improved at https://github.com/mapbox/mapbox-gl-js/blob/master/CONTRIBUTING.md#version-control-conventions. It should just be a matter of (on your-branch) |
Nah that is fine and makes sense, I wouldn't propose to decide for everyone what is best. My 2¢ personal opinion is that when using Github, merging is the best workflow since all the "compare" Github features are built with that assumption in place. Hacks like |
Motivation
The default GeolocateControl shows the viewer's position as reported by
navigator.geolocation.watchPosition
immediately, but this often has a very high margin of error. The dot is often in the wrong location, which can be confusing or even dangerous depending on the application.Implementation
Adds a transparent circle to GeolocateControl showing the accuracy of the position, as reported by
navigator.geolocation.watchPosition
.Launch Checklist
@mapbox/studio
and/or@mapbox/map-design-team
if this PR includes style spec or visual changesGeolocateControl
that shows the reported location accuracy. Toggled byshowAccuracy
option which defaults totrue
.