Describe the bug
MapView's onUserLocationUpdate doesn't seem to fire.
To Reproduce
onUserLocationUpdate = (location) => {
console.log('location',location);
}
render() {
return (
<MapboxGL.MapView
animated
ref={c => this.map = c}
styleURL={this.props.theme.styleURL}
onUserLocationUpdate={this.onUserLocationUpdate}
onPress={this.onPress}
logoEnabled={false}
compassEnabled={false}
pitchEnabled={false}
onRegionWillChange={this.onRegionWillChange}
style={{ flex: 1 }}
onDidFinishLoadingMap={this.onDidFinishLoadingMap}
onDidFinishRenderingMap={this.onDidFinishRenderingMap}
onDidFinishRenderingMapFully={this.onDidFinishRenderingMapFully}
onDidFinishLoadingStyle={this.onDidFinishLoadingStyle}
onUserLocationUpdate={this.onUserLocationUpdate}
>
<MapboxGL.UserLocation visible={true} renderMode="custom">
<MapboxGL.CircleLayer id="mapboxUserLocationPluseCircle" style={layerStyles.normal.pulse} />
<MapboxGL.CircleLayer id="mapboxUserLocationWhiteCircle" style={layerStyles.normal.background} />
<MapboxGL.CircleLayer id="mapboxUserLocationBlueCicle" aboveLayerID="mapboxUserLocationWhiteCircle" style={layerStyles.normal.foreground} />
</MapboxGL.UserLocation>
<MapboxGL.Camera
followUserLocation={this.state.currentTrackingModeIsFollowing}
followUserMode="course"
onUserTrackingModeChange={this.onUserTrackingModeChange}
/>
</MapboxGL.MapView>
)
}
Expected behavior
Expected onUserLocationUpdate to fire the callback
Screenshots
N/A
Versions (please complete the following information):
Additional context
Just doesn't seem to fire. I searched the repo's source code and not sure why it could be not working - seems like onUserLocationUpdate is still a prop of MapView, not Camera. Not quite sure if it's because of some props i'm passing in. Was working fine 6.1.2
It does not work at all, even on the example. Waiting for the response about it.
@nitaliano any update on this would be appreciated
Using this method as well, not listed in documentation. Has it been deprecated/removed?
Iām unclear on this as well.. anyone in community have insight into this?
just using react-native-location meanwhile
Looks like you need to set the userTrackingMode prop:
It not there I think
I use the UserLocation
<Mapbox.UserLocation visible={true} onUpdate={onUpdate} />
With that on update you need to check if the distance between the old and the new point is greater than ... or else you have an update every second.
It's also not in the source code so you have to use UserLocation component
https://github.com/react-native-mapbox-gl/maps/blob/master/javascript/components/MapView.js
Any news on the above? What's the best solution?
can confirm that @RichardLindhout solution seems to be the new way to go:
The documentation is sparse, however it mentions onUpdate docs
@ferdicus you have to debounce this onUpdate since it fires at least every second and without any movement.
this weird, haven't checked the native code, however isn't it using some sort of underlying watchPosition?
thx anyways
You should log it, it's extreme how much update
My HOC component (I have a shared codebase with react-native-web)
import React, { useState, useCallback } from 'react'
import { useDebouncedCallback } from 'use-debounce'
import { distance } from './helpers'
export default function MapUserLocationHOC(WrappedComponent) {
function Enhanced({ onUserLocationUpdate, ...rest }) {
const [previousLocation, setPreviousLocation] = useState(null)
const onUpdateCoords = useCallback(
({ coords }) => {
if (!coords) {
// console.log('no args to debounced location update')
return
}
let needsUpdate = false
if (previousLocation) {
const dist = distance(previousLocation, coords, 'CM')
if (dist > 30) {
needsUpdate = true
}
} else {
needsUpdate = true
}
if (needsUpdate) {
setPreviousLocation(coords)
// let other component know user location has changed
onUserLocationUpdate && onUserLocationUpdate(coords)
}
},
[previousLocation, setPreviousLocation, onUserLocationUpdate]
)
const [onDebouncedUpdate] = useDebouncedCallback(
// function
onUpdateCoords,
// delay in ms
600,
{ maxWait: 2000 }
)
return <WrappedComponent {...rest} onDebouncedUpdate={onDebouncedUpdate} />
}
return Enhanced
}
// https://www.geodatasource.com/developers/javascript
export function distance(location1, location2, unit) {
const lat1 = location1.latitude
const lon1 = location1.longitude
const lat2 = location2.latitude
const lon2 = location2.longitude
if (lat1 === lat2 && lon1 === lon2) {
return 0
} else {
var radlat1 = (Math.PI * lat1) / 180
var radlat2 = (Math.PI * lat2) / 180
var theta = lon1 - lon2
var radtheta = (Math.PI * theta) / 180
var dist =
Math.sin(radlat1) * Math.sin(radlat2) +
Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta)
if (dist > 1) {
dist = 1
}
dist = Math.acos(dist)
dist = (dist * 180) / Math.PI
dist = dist * 60 * 1.1515
if (unit === 'K') {
dist = dist * 1.609344
}
if (unit === 'M') {
dist = dist * 1.609344 * 1000
}
if (unit === 'CM') {
dist = dist * 1.609344 * 1000 * 100
}
if (unit === 'N') {
dist = dist * 0.8684
}
return dist
}
}
import React from 'react'
import Mapbox from '@react-native-mapbox-gl/maps'
import MapUserLocationHOC from './MapUserLocationHOC'
function MapUserLocation({ onDebouncedUpdate }) {
return (
<Mapbox.UserLocation
// visible={Platform.OS === 'ios'}
visible={false}
animated
onUpdate={onDebouncedUpdate}
showUserLocation={true}
/>
)
}
export default MapUserLocationHOC(MapUserLocation)
yeah, I've noticed that it's firing in a very high interval, even when immobile.
That's quite a workaround š
However, that there must be a more suitable solution, no?
š
Probably, (maybe by only checking difference in long / lat) but I'm doing some fairly heavy things after a location update, so I don't want to do that every second. I think somethings like this is the only way since it keeps firing location events even if my device does not do anything.
But I think this should be handled in te library in the native thread, since I think all the debounces are fairly memory heavy. Have no proof for that though :)
We should create a throttle control for this and onRegionIsChanging similar
to ScrollView onScroll. The throttle should happen on native side to
prevent unnecessary bridge activity.
Happy to see a PR for this. The RN core ScrollView can be a good source of
inspiration for this code.
On Wed, 30 Oct 2019 at 19:39, Richard Lindhout notifications@github.com
wrote:
Probably, (maybe by only checking difference in long / lat) but I'm doing
some fairly heavy things after a location update, so I don't want to do
that every second. I think somethings like this is the only way since it
keeps firing location events even if my device does not do anything.But I think this should be handled in te library in the native thread,
since I think all the debounces are fairly memory heavy. Have no proof for
that though :)ā
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/react-native-mapbox-gl/maps/issues/246?email_source=notifications&email_token=ABLAPW5MGSAC2IK563FHBHLQRHIELA5CNFSM4IDSMAX2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOECVKYII#issuecomment-548056097,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/ABLAPW5W4FLFZPADJSIC52TQRHIELANCNFSM4IDSMAXQ
.
We could also copy some some code from here, looks like this is better than throttling since it will fire constantly with throttle also.
https://github.com/react-native-community/react-native-geolocation/blob/master/android/src/main/java/com/reactnativecommunity/geolocation/GeolocationModule.java#L390
LOG onUpdateCoords {"coords": {"accuracy": 9.977999687194824, "altitude": 44.64373779296875, "heading": 251.5358428955078, "latitude": 51.5462244, "longitude": 4.1036916, "speed": 0.08543474227190018}, "timestamp": 1573730357879}
LOG onUpdateCoords {"coords": {"accuracy": 7.492000102996826, "altitude": 44.64373779296875, "heading": 252.25204467773438, "latitude": 51.5462242, "longitude": 4.1036905, "speed": 0.07626981288194656}, "timestamp": 1573730359000}
LOG onUpdateCoords {"coords": {"accuracy": 6.244999885559082, "altitude": 45.210205078125, "heading": 336.17572021484375, "latitude": 51.5462262, "longitude": 4.1036887, "speed": 0.07873588800430298}, "timestamp": 1573730362000}
LOG onUpdateCoords {"coords": {"accuracy": 4.980999946594238, "altitude": 45.610595703125, "heading": 339.0922546386719, "latitude": 51.5462276, "longitude": 4.1036883, "speed": 0.08173366636037827}, "timestamp": 1573730364000}
LOG onUpdateCoords {"coords": {"accuracy": 3.9070000648498535, "altitude": 45.87335205078125, "heading": 280.903564453125, "latitude": 51.5462283, "longitude": 4.1036871, "speed": 0.012436928227543831}, "timestamp": 1573730369000}
LOG onUpdateCoords {"coords": {"accuracy": 5.051000118255615, "altitude": 46.19677734375, "heading": 128.6796417236328, "latitude": 51.5462299, "longitude": 4.1036876, "speed": 0.0030809876043349504}, "timestamp": 1573730419000}
LOG onUpdateCoords {"coords": {"accuracy": 6.9670000076293945, "altitude": 46.1929931640625, "heading": 169.62660217285156, "latitude": 51.5462298, "longitude": 4.1036876, "speed": 0.0038356157019734383}, "timestamp": 1573730421000}
LOG onUpdateCoords {"coords": {"accuracy": 8.170999526977539, "altitude": 46.1932373046875, "heading": 181.6247100830078, "latitude": 51.5462298, "longitude": 4.1036876, "speed": 0.0013805326307192445}, "timestamp": 1573730423000}
LOG onUpdateCoords {"coords": {"accuracy": 9.817999839782715, "altitude": 46.19488525390625, "heading": 357.03167724609375, "latitude": 51.5462298, "longitude": 4.1036876, "speed": 0.0023486786521971226}, "timestamp": 1573730424000}
When I have my phone on the table for 20 seconds this is the results now in my javascript code, instead of firing constantly.
Interestingly I've noticed, that it not always fires like crazy, sometimes it's less frequent, sometimes more... I also only monitor it via remote debugger when in the office.
My device is enormous it even does fire every second when my devices lies on the table without touching it ;)
BTW, I changed the implementation a little bit to check if location change is more than 10cm
boolean isSignificant = isMoreAccurate ? distance > 10 : distance > 100;
Thats like more than 4 inches.
The events get fired because the heading changes. I filtered this out and it helped a lot.
I've found onUpdate on UserLocation doesn't always call to process a first initial location when opening the app, either - though sometimes it does - any ideas?
I believe this can be closed.
UserLocation updates are firing via:
<MapboxGL.UserLocation onUpdate={// your callback goes here }/>
And the issue with the frequency of position updates was addressed by the minDisplacement property.
Most helpful comment
We should create a throttle control for this and onRegionIsChanging similar
to ScrollView onScroll. The throttle should happen on native side to
prevent unnecessary bridge activity.
Happy to see a PR for this. The RN core ScrollView can be a good source of
inspiration for this code.
On Wed, 30 Oct 2019 at 19:39, Richard Lindhout notifications@github.com
wrote: