maps
maps copied to clipboard
setCamera doesn't take effect if followUserLocation set to true
Describe the bug setCamera doesn't take effect if followUserLocation set to true
To Reproduce
set Camera's component followUserLocation prop to true and try to call setCamera on it's ref
Example:
const MapView = (props) => {
const resetRotation = useCallback(() => {
camera.current?.setCamera({
heading: 0,
animationDuration: 200,
});
}, []);
return (
<MapboxGL.MapView>
<MapboxGL.Camera
ref={camera}
followUserLocation
followUserMode={'normal'}
/>
</MapboxGL.MapView>
);
};
Expected behavior it should be possible to setCamera or at least some of it's props in case followUserLocation===true while i see there can be some conflict updating the coords (which one should be prioritized?) at least zoomLevel, pitch and rotation should be just fine
Screenshots
Versions (please complete the following information):
- Platform:both ios and android
- react-native-mapbox-gl 8.1.0-rc.4, 8.1.0-rc.6
- React Native Version 0.62
inspecting the code i've found following
_createStopConfig(config = {}, ignoreFollowUserLocation = false) {
if (this.props.followUserLocation && !ignoreFollowUserLocation) {
return null;
}
...
}
setCamera(config = {}) {
this._setCamera(config);
}
_setCamera(config = {}) {
let cameraConfig = {};
if (config.stops) {
cameraConfig.stops = [];
for (const stop of config.stops) {
cameraConfig.stops.push(this._createStopConfig(stop));
}
} else {
cameraConfig = this._createStopConfig(config);
}
this.refs.camera.setNativeProps({stop: cameraConfig});
}
wouldn't it make sense to at least provide possibility to pass ignoreFollowUserLocation as the Camera.setCamera fc parameter?
hey @nasmuris, sounds reasonable to me - would you be willing to open a PR for this?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I'd say this is a particularly important feature right now because in order for UserLocation renderMode to be native on android, Camera followUserLocation must be true, but if followUserLocation is true, setCamera can't be used! Can we reopen?
Right, I believe that is the current status on setCamera. I'm wondering if we can get it consistent with how the iOS version works?
I'll reopen this - and yes, would be great if someone could take a jab at this. I could try, however I can't make any promises to when it would be done
as a workaround for not being able to use setCamera atm, did you see, that you could simply use these three, they would work for exactly the settings you'd like to edit @nasmuris :
| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
followZoomLevel |
number | none | false | The zoomLevel on map while followUserLocation is set to true |
followPitch |
number | none | false | The pitch on map while followUserLocation is set to true |
followHeading |
number | none | false | The heading on map while followUserLocation is set to true |
Same issue here, as a workaround could you please give an example how to use these attributes ?, I have navigation mode map which use followUserLocation, if user moved the map and clicked on center button I want to get back to current location. @ferdicus
I'd say this is a particularly important feature right now because in order for UserLocation renderMode to be native on android, Camera followUserLocation must be true, but if followUserLocation is true, setCamera can't be used! Can we reopen?
Not sure if this would help in your case, but I currently set followUserLocation back to false once the map style has been initialised. This way I can carry on setting custom Camera coordinates. Something like this:
import React, {useState, useEffect, useRef} from 'react';
import {Platform, View} from 'react-native';
import MapboxGL from '@react-native-mapbox-gl/maps';
...
export default function MapScreen(props) {
const cameraRef = useRef();
const [followUser, setFollowUser] = useState(Platform.OS === 'android');
useEffect(() => {
if (!followUser && cameraRef?.current) {
cameraRef.current.moveTo([-3.0886, 54.539627], 300);
}
}, [followUser]);
return (
<View style={styles.container}>
<MapboxGL.MapView
style={styles.map}
styleURL={STYLE_URL}
onDidFinishLoadingStyle={() => {
if (followUser) {
// Required for Android heading indicator,
// triggers effect to focus camera on init values
setFollowUser(false);
}
}}>
<MapboxGL.Camera
ref={cameraRef}
// native for Android, only works if followUserLocation set to true
followUserLocation={followUser}
zoomLevel={11}
centerCoordinate={[-3.0886, 54.539627]}
animationMode={'flyTo'}
animationDuration={1900}
/>
<MapboxGL.UserLocation
visible={true}
renderMode={'native'}
// Android indicator set via androidRenderMode
showsUserHeadingIndicator={Platform.OS === 'ios'}
// native/android only render mode (compass: triangle with heading)
androidRenderMode={'compass'}
/>
</MapboxGL.MapView>
</View>
);
}
Same issue here, as a workaround could you please give an example how to use these attributes ?, I have navigation mode map which use followUserLocation, if user moved the map and clicked on center button I want to get back to current location. @ferdicus
This is not an issue - please refer to the gitter chat/ stackoverflow or Discussions for usage advise
@ferdicus Sorry for being unable to reply for such a long time, but this bug/feature had low prio for my project and I haven't had enought time to dig into this in my free time...
As a quick fix, I'll try to implement the ignoreFollowUserLocation param, if it works fine for me, I'll create a PR ASAP :)
I'm still not sure whether this is proper solution though, but better than nothing, right?
Same problem here. I'm trying to change the pitch based on the navigation mode but the problem is that when the user location updates at the same time the camera's animation stops. For example, if i change dynamically the navigation mode to "course" and the pitch to 50, the camera will start the animation to fit to the new pitch but if the user location updates at the same time then the camera's animation will instantly stop.
This also seem to affect camera.flyTo as well as changing the centerCoordinate dynamically using a state. When followUserLocation is set to true, both dont work, but if false, it works fine.
@gokugen - did you try Camera => followPitch
@bobokeke0 - I mean, those two are exclusive, how should the camera follow the user position and at the same time center the coordinate to a specific location? You have to chose one
@ferdicus yes even with followPitch there was a problem. I've simply resolved this by setting setFollowUserLocation to false then change the Pitch then reset it to true.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Hi stale bot, so in your mind, things without activity are fixed? Robots...
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Activity is happening.
is there a workaround for this yet? I can't have followUser but also flyTo?
Also experiencing this and a solution in the api would be much appreciated (something like the ignoreFollowUserLocation property on setCamera as proposed above). flyTo is also not doing anything if followUserLocation is set to true.
The only solution we've come up so far is to set followUserLocation to false, listen in a useEffect on it and only then call setCamera such that one render happens in between and the state change kicks in:
const [coordinates, setCoordinates] = useState<Coordinates>(null)
const [followUserLocation, setFollowUserLocation] = useState<boolean>(true)
const flyTo = (coordinates: Coordinates) => {
setFollowUserLocation(false)
setCoordinates(coordinates)
}
useEffect(() => {
if (!followUserLocation && coordinates) {
cameraRef.current.flyTo(coordinates)
}
}, [followUserLocation, coordinates])
...
Has anybody been able to find a solution to this issue? I’m having it on Android (only when targeting Android 12 for some reason). Same code working on iOS without issues even if followUserLocation is set to true.
My environment: RN version: 0.68.4 Version of this library: 8.5.0
Activity is happening
I understand that you people might think that it doesn't make sense to allow a setCamera, moveTo or flyTo operation to be performed when the user wants the map to follow location, but there are a bunch of cases where you wanna change some camera properties without the need to turn off followUserLocation, just to turn it back on once the camera change has been performed.
Plus, on iOS, this is not happening, and PLEASE don't change that 😅. I mean, I might want to change the zoom, the pinch and other properties, and I cannot do anything like that without this on/off, which sucks because I need to trigger a rerender uselessly... Are you sure it makes sense to keep it that way?
@whiteHatCip But it's not clear how flyTo/moveTo etc. should behave when followLocation is true. If you want to use flyTo/moveTo just disable followLocation, why is it an issue?
Zoom, pitch etc can be changed with changing followZoomLevel and followPitch
The problem is that I start my application with the followUserLocation set to true, then the new coordinates for the current location arrive, but the camera doesn't move on it's own to the current location, and specifically with the desired zoom level, to say one example. This thing is not a problem on iOS, why should it be on Android? Have you tried removing any check over the followUserLocation value from the setCamera method implementation on the native side? Otherwise I might simply apply a patch on my own local project, but I don't really know where to put my hands on, since I'm not that savvy about kotlin...so, any suggestion to allow me do what I would like to achieve would be good anyway.
Agreeing with @whiteHatCip here. In order to achieve a moveTo if followUserLocation is set to true we have to use this workaround: https://github.com/rnmapbox/maps/issues/1079#issuecomment-1203964181 In our opinion this is a perfectly normal use case that is a little bit overly complicated to achieve.
@steffenkleinle If I may add another consideration about the workaround, you have to always make sure that the condition to perform the move/fly to coordinates is always correct, meaning that if you don't want to flit, you have to make sure that in the https://github.com/rnmapbox/maps/issues/1079#issuecomment-1203964181 workaround the coordinates state variable is set to nil. I mean, I understand that this is a manageable thing, but it's a needless complication. and as I said, I cannot even simply change the zoom level by using the camera api, despite changing the zoom would simply change this property, and not the camera center coordinate, meaning that the camera would still follow the user location, but the camera is totally immutable because of the current implementation, and this makes no sense, in my opinion.