Closed timweii closed 1 month ago
Hi @timweii, I have done this in rnmapbox/maps
without modifying the library, and the same should work in maplibre-react-native
using react-native-reanimated createAnimatedComponent
and useAnimatedProps
.
Something like this should work:
import Animated, { useAnimatedProps } from 'react-native-reanimated';
import { createAnimatedPropAdapter } from 'react-native-reanimated/src/reanimated2/PropAdapters';
const [followPoint, setFollowPoint] = useState(null);
const AnimatedShape = Animated.createAnimatedComponent(Maplibre.ShapeSource);
const animatedProps = useAnimatedProps(
() => {
const shape = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {
type: 'generalMarker',
icon: 'example',
id: 'generalMarker'
},
geometry: {
type: 'Point',
coordinates: followPoint
},
},
],
}
return { shape };
},
null,
shapeAdapter
);
<AnimatedShape id="exampleShapeSource" animatedProps={animatedProps}>
<MapLibre.CircleLayer id="singlePoint" style={layerStyle.singlePoint} />
</AnimatedShape>
Hi @tyrauber, thank you for getting back to me. I've created a basic animation component to try out your code (see attached below). However, it throws an error when the second followPoint is passed.
Exception in HostFunction: com.facebook.react.bridge.JSApplicationIllegalArgumentException: Error while updating property 'shape' of a view managed by: RCTMGLShapeSource
I am wondering if it encounters a similar issue when attempting to animate a marker view:
In the android/rctmgl/src/main/java/com/mapbox/rctmgl/components/annotation/RCTMGLMarkerViewManager.java
file, the setCoordinate
method expects a geoJSON string
. However, in the current version of rnmapbox/maps
, it's expecting an array - so the animation can update the props success because they are the same format?
Could this difference potentially cause failure?
Similarly, in components/ShapeSource.tsx
, the RCTMGLShapeSource
expects shape props
as a JSONString. but during animation, it updates the shape with a geoJSON object instead of a JSONString, which could lead to failures?
import Animated, { useAnimatedProps, useSharedValue } from 'react-native-reanimated';
import { ShapeSource, CircleLayer } from '@app/lib/map';
import { useEffect } from 'react';
const layerStyle = {
singlePoint: {
circleRadius: 5,
circleColor: '#FF6347',
circleStrokeWidth: 1,
circleStrokeColor: '#FFFFFF',
},
};
const AnimatedShape = Animated.createAnimatedComponent(ShapeSource);
export default ({ followPoint }) => {
const animatedFollowPoint = useSharedValue(followPoint);
useEffect(() => {
animatedFollowPoint.value = followPoint;
}, [followPoint]);
const animatedProps = useAnimatedProps(
() => ({
shape: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {
type: 'generalMarker',
id: 'generalMarker',
},
geometry: {
type: 'Point',
coordinates: animatedFollowPoint.value,
},
},
],
},
}),
[animatedFollowPoint]
);
return (
<AnimatedShape id='exampleShapeSource' animatedProps={animatedProps}>
<CircleLayer id='singlePoint' style={layerStyle.singlePoint} />
</AnimatedShape>
);
};
Hi @timweii, You are correct. The native libraries are expecting JSON, but the JS API should handle the conversion.
If you look at ShapeSource, it says it accepts a GeoJSON geometry, a feature, or a feature colllection
and setNativeProps converts the GeoJSON to a JSON string before passing it to the native library, so that should be ok.
But, try whitelisting the native props:
const AnimatedShape = Animated.createAnimatedComponent(ShapeSource);
//Animated.addWhitelistedUIProps({ shape: true });
Animated.addWhitelistedNativeProps({ shape: true });
If that doesn't work, try converting the shape prop to JSON manually:
const shapeAdapter = createAnimatedPropAdapter((props) => {
props.shape = JSON.stringify(props.shape);
})
Let me know what you find!
Thank you @tyrauber! Animated.addWhitelistedNativeProps({ shape: true })
works perfectly. Closing this issue now.
Hello, I'd like to request an enhancement for animating the MarkerView using
react-native-reanimated
. This feature has been successfully implemented inrnmapbox/maps
. That would be great if we can also have this feature available inmaplibre-react-native
as well. Could this enhancement be considered?Thanks!
Reference: Discussion: https://github.com/rnmapbox/maps/discussions/3097 Commit: https://github.com/jleprinc/rnmapbox-animation/commit/71819c75d045df0e5f87ed85a706b6d55dba4204