Closed mlecoq closed 2 years ago
I'm also experiencing this issue with react-native-svg
on v13.0.0 (after upgrading from v12.1.0). My setup:
System:
OS: macOS 12.5.1
CPU: (10) arm64 Apple M1 Pro
Memory: 105.06 MB / 16.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 16.13.1 - /var/folders/md/1qkynwbs1216d57grkbc682h0000gn/T/fnm_multishells/19554_1661241167202/bin/node
Yarn: 1.22.15 - /var/folders/md/1qkynwbs1216d57grkbc682h0000gn/T/fnm_multishells/19554_1661241167202/bin/yarn
npm: 8.1.2 - /var/folders/md/1qkynwbs1216d57grkbc682h0000gn/T/fnm_multishells/19554_1661241167202/bin/npm
Watchman: 2022.03.21.00 - /opt/homebrew/bin/watchman
Managers:
CocoaPods: 1.11.3 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 21.4, iOS 15.5, macOS 12.3, tvOS 15.4, watchOS 8.5
Android SDK: Not Found
IDEs:
Android Studio: 2020.3 AI-203.7717.56.2031.7935034
Xcode: 13.4.1/13F100 - /usr/bin/xcodebuild
Languages:
Java: 11.0.13 - /usr/bin/javac
npmPackages:
@react-native-community/cli: Not Found
react: 18.0.0 => 18.0.0
react-native: 0.69.4 => 0.69.4
react-native-macos: Not Found
npmGlobalPackages:
*react-native*: Not Found
I am experiencing a similar issue as well
It is the effect of both Paper and Fabric implementations using delegates and interfaces added with Fabric integration. Due to problems with codegen, all props are now stringified in render
methods, and color
related props are parsed differently now too. Due to those changes, when using reanimated
, you also have to stringify all props that were previously of type NumberProp
, and parse props of color
type acordingly. For your use-case, it would be something like this:
return {
cx: String(coordinates.cx),
cy: String(coordinates.cx),
rx: String(coordinates.rx),
ry: String(coordinates.ry),
stroke: {type: 0, value: processColor('rgb(0,0,0)')},
opacity: 0,
strokeWidth: String(0),
};
Unfortunately there seems to be a bug in reanimated
codebase since stroke
prop cannot be parsed in my testing env. We will try to come up with a more generic solution for this soon hopefully.
@WoLewicki thanks for your explanations, yes I started first to stringify params but since my code was failing on stroke (which expects ReadableMap), I did not dig any further.
Seeing what I think is the same issue here upon trying to upgrade to 13.0.0. java.lang.Double cannot be cast to com.facebook.react.bridge.ReadableMap
at setProperty RNSVGTextManagerDelegate.java
Hi there, I add this here. I have no animation with react-content-loader since react-native-svg 13.0.0 only on Android. Everything works fine on iOS. And I have a fatal crash with this error:
Fatal Exception: java.lang.NullPointerException
Attempt to invoke virtual method 'java.lang.String java.lang.String.trim()' on a null object reference
com.horcrux.svg.SVGLength.<init> (SVGLength.java:37)
This library doesn't use reanimated but seems to use animation from react-native.
Here an content-loader example:
<ContentLoader
viewBox="0 0 360 100"
height={100}
width={360}
backgroundColor={'#333'}
foregroundColor="#999">
<Circle x="70" y="20" cx="20" cy="20" r="20" />
<Rect x="110" y="38" rx="0" ry="0" width="20" height="4" />
<Circle x="130" y="20" cx="20" cy="20" r="20" />
<Rect x="170" y="38" rx="0" ry="0" width="20" height="4" />
<Circle x="190" y="20" cx="20" cy="20" r="20" />
<Rect x="230" y="38" rx="0" ry="0" width="20" height="4" />
<Circle x="250" y="20" cx="20" cy="20" r="20" />
</ContentLoader>
Is this bug fixed in 13.1.0? @WoLewicki
Unfortunately I don't think it is. Since react-native-reanimated
updates the props directly and does not go through render method, the typings may differ there leading to a crash 😞
Guys, If i want to use fill
property via useAnimatedProps
.
Example:
const animatedProps = useAnimatedProps(() => {
return {
fill: "#cccccc",
};
}
<AnimatedEllipse animatedProps={animatedProps} />
In version 12.3.0 it is working, on 13+ i have similar error. Or i do something incorrect?
Unfortunately super weird behavior on Android with Reanimated, useAnimatedProps barely seems to work anymore :/
This code worked well in 12.4.0, but does not work now (no crash, but it does nothing):
const animatedProps = useAnimatedProps(() => {
const pos = getPositionOnCircle(angle.value)
const x2 = pos.x
const y2 = pos.y
const degrees = toDeg(angle.value) + 90
return {
x: x2,
y: y2,
transform: [{ rotate: `${degrees}deg` }],
}
})
Hi there, I add this here. I have no animation with react-content-loader since react-native-svg 13.0.0 only on Android. Everything works fine on iOS. And I have a fatal crash with this error:
Fatal Exception: java.lang.NullPointerException Attempt to invoke virtual method 'java.lang.String java.lang.String.trim()' on a null object reference com.horcrux.svg.SVGLength.<init> (SVGLength.java:37)
This library doesn't use reanimated but seems to use animation from react-native.
Here an content-loader example:
<ContentLoader viewBox="0 0 360 100" height={100} width={360} backgroundColor={'#333'} foregroundColor="#999"> <Circle x="70" y="20" cx="20" cy="20" r="20" /> <Rect x="110" y="38" rx="0" ry="0" width="20" height="4" /> <Circle x="130" y="20" cx="20" cy="20" r="20" /> <Rect x="170" y="38" rx="0" ry="0" width="20" height="4" /> <Circle x="190" y="20" cx="20" cy="20" r="20" /> <Rect x="230" y="38" rx="0" ry="0" width="20" height="4" /> <Circle x="250" y="20" cx="20" cy="20" r="20" /> </ContentLoader>
Have similar issue, when I try to animate SVG app crashes .
Can you check if applying https://github.com/react-native-svg/react-native-svg/pull/1869 fixes your issue? Make sure to correctly treat fill
and stroke
props. Example of it can be found in the test case: https://github.com/react-native-svg/react-native-svg/pull/1869/files#diff-76a76277daf14518270e8aea8a5e9358a8215d7e4276d2e5f1c4fe95107cdc20
@WoLewicki I have tried your PR on the following example https://github.com/mlecoq/reactNativeSvg13 and it still crashes
java_vm_ext.cc:578] JNI DETECTED ERROR IN APPLICATION: JNI GetObjectRefType called with pending exception java.lang.RuntimeException: Exception in HostFunction: java.lang.ClassCastException: java.lang.String cannot be cast to com.facebook.react.bridge.ReadableMap
java_vm_ext.cc:578]
java_vm_ext.cc:578] [native code]
java_vm_ext.cc:578]
I have tried to replace
stroke: 'rgb(0,0,0)',
with
stroke: {type: 0, value: processColor('rgb(0,0,0)')},
and I have the following error
Error: invalid value passed to `stroke`, maybe you forgot to use `.value`?
As pointed in the https://github.com/react-native-svg/react-native-svg/issues/1845#issuecomment-1247009705, the best way to handle fill
and stroke
props in by using createAnimatedPropAdapter
which was made for this particular case, where props on the native side have different structure than in JS. Also, I changed the value
prop to payload
so it does not confuse reanimated
babel plugin. Your animatedProps
should look e.g. like this:
const ellipseAnimatedProps =
useAnimatedProps(() =>
{
const coordinates = {cx: 50, cy: 50, rx: 40, ry: 40};
return {
cx: coordinates.cx,
cy: coordinates.cy,
rx: coordinates.rx,
ry: coordinates.ry,
stroke: 'rgb(255,0,0)',
fill: 'yellow',
opacity: offset.value,
strokeWidth: 2,
};
}
, [], createAnimatedPropAdapter(
(props) => {
if (Object.keys(props).includes('fill')) {
props.fill = {type: 0, payload: processColor(props.fill)}
}
if (Object.keys(props).includes('stroke')) {
props.stroke = {type: 0, payload: processColor(props.stroke)}
}
},
['fill', 'stroke']));
Yes I just saw your example with the adapter, it works fine now, thanks a lot !
Ok I will close this issue then. Feel free to comment here if something is wrong and we can always reopen it then.
I am just wondering how to fix this error using react-native
s Animated
API?
Here is an Example which is not working on the current main
:
java.lang.String cannot be cast to com.facebook.react.bridge.ReadableMap
const animation = React.useRef(new Animated.Value(0));
React.useEffect(() => {
Animated.timing(animation.current, {
toValue: 1,
duration: 300,
delay: 100,
easing: Easing.out(Easing.quad),
useNativeDriver: false,
}).start();
}, []);
return (
<SafeAreaView>
<Svg width={40} height={40} viewBox="0 0 40 40" fill="none">
<AnimatedPath
fill={animation.current.interpolate({
inputRange: [0, 0.4, 1],
outputRange: ['#1F1F34', '#FFD761', '#FA9502'],
})}
d="M16.0489 0.927051C16.3483 0.00574017 17.6517 0.00574017 17.9511 0.927051L21.2658 11.1287C21.3996 11.5407 21.7836 11.8197 22.2168 11.8197H32.9434C33.9122 11.8197 34.3149 13.0593 33.5312 13.6287L24.8532 19.9336C24.5027 20.1883 24.3561 20.6396 24.4899 21.0517L27.8046 31.2533C28.104 32.1746 27.0495 32.9407 26.2658 32.3713L17.5878 26.0664C17.2373 25.8117 16.7627 25.8117 16.4122 26.0664L7.73419 32.3713C6.95048 32.9407 5.896 32.1746 6.19535 31.2533L9.51006 21.0517C9.64393 20.6396 9.49728 20.1883 9.14679 19.9336L0.468768 13.6287C-0.314945 13.0593 0.0878303 11.8197 1.05655 11.8197H11.7832C12.2164 11.8197 12.6004 11.5407 12.7342 11.1287L16.0489 0.927051Z"
/>
</Svg>
</SafeAreaView>
);
Turns out my java.lang.Double cannot be cast to com.facebook.react.bridge.ReadableMap
was just a misleading error message. Double check the props you're passing to <SVG
-- I was accidentally passing an empty string ""
for the fill
prop on an svg text element. For some reason that got converted to a java.lang.Double
resulting in the confusing error message.
I am just wondering how to fix this error using react-natives Animated API?
You need to comply to the format of fill
prop that is passed to the native side (since the props are not going through render
and are not parsed by the lib), which is defined e.g. here: https://github.com/software-mansion/react-native-svg/blob/9c0fa78d72c9e32644b10f55090ae29edd1f5856/src/fabric/PathNativeComponent.ts#L25
Can you try if applying this commit: 4d16dc4
(#1914) fixes the problem?
@WoLewicki thank you it works like a charm 😍
Turns out my
java.lang.Double cannot be cast to com.facebook.react.bridge.ReadableMap
was just a misleading error message. Double check the props you're passing to<SVG
-- I was accidentally passing an empty string""
for thefill
prop on an svg text element. For some reason that got converted to ajava.lang.Double
resulting in the confusing error message.
You have certainly saved me days of headaches!
I am just wondering how to fix this error using react-natives Animated API?
You need to comply to the format of
fill
prop that is passed to the native side (since the props are not going throughrender
and are not parsed by the lib), which is defined e.g. here:Can you try if applying this commit:
4d16dc4
(#1914) fixes the problem?
Can a similar fix be put in place for the stroke
prop? Or is there a future plan to fix this properly?
Can we add this solution to the docs?
As pointed in the #1845 (comment), the best way to handle
fill
andstroke
props in by usingcreateAnimatedPropAdapter
which was made for this particular case, where props on the native side have different structure than in JS. Also, I changed thevalue
prop topayload
so it does not confusereanimated
babel plugin. YouranimatedProps
should look e.g. like this:const ellipseAnimatedProps = useAnimatedProps(() => { const coordinates = {cx: 50, cy: 50, rx: 40, ry: 40}; return { cx: coordinates.cx, cy: coordinates.cy, rx: coordinates.rx, ry: coordinates.ry, stroke: 'rgb(255,0,0)', fill: 'yellow', opacity: offset.value, strokeWidth: 2, }; } , [], createAnimatedPropAdapter( (props) => { if (Object.keys(props).includes('fill')) { props.fill = {type: 0, payload: processColor(props.fill)} } if (Object.keys(props).includes('stroke')) { props.stroke = {type: 0, payload: processColor(props.stroke)} } }, ['fill', 'stroke']));
Bonjour, Je suis désolée, je ne sais pas exactement de quoi vous parler mais pas soucis évidemment et merci ^^
Envoyé à partir de Outlook pour iOShttps://aka.ms/o0ukef
De : Valery Smirnov @.> Envoyé : Monday, June 19, 2023 10:54:08 AM À : software-mansion/react-native-svg @.> Cc : Subscribed @.***> Objet : Re: [software-mansion/react-native-svg] [Android] [Reanimated] crash with react-native-svg 13.0.0 (Issue #1845)
Can we add this solution to the docs?
As pointed in the #1845 (comment)https://github.com/software-mansion/react-native-svg/issues/1845#issuecomment-1247009705, the best way to handle fill and stroke props in by using createAnimatedPropAdapter which was made for this particular case, where props on the native side have different structure than in JS. Also, I changed the value prop to payload so it does not confuse reanimated babel plugin. Your animatedProps should look e.g. like this:
const ellipseAnimatedProps = useAnimatedProps(() => { const coordinates = {cx: 50, cy: 50, rx: 40, ry: 40};
return {
cx: coordinates.cx,
cy: coordinates.cy,
rx: coordinates.rx,
ry: coordinates.ry,
stroke: 'rgb(255,0,0)',
fill: 'yellow',
opacity: offset.value,
strokeWidth: 2,
};
} , [], createAnimatedPropAdapter( (props) => { if (Object.keys(props).includes('fill')) { props.fill = {type: 0, payload: processColor(props.fill)} } if (Object.keys(props).includes('stroke')) { props.stroke = {type: 0, payload: processColor(props.stroke)} } }, ['fill', 'stroke']));
— Reply to this email directly, view it on GitHubhttps://github.com/software-mansion/react-native-svg/issues/1845#issuecomment-1596779135, or unsubscribehttps://github.com/notifications/unsubscribe-auth/A7NVM2QTUYESKXSBXVH7LZLXMAHTBANCNFSM57KW7YWQ. You are receiving this because you are subscribed to this thread.Message ID: @.***>
I'm still facing the issue on Android, Animation starts asusual but after a while I see an error on Device but it doesnt appear on console
Here is how it looks on device
Can you help @WoLewicki
Are you sure you are not changing the type of the prop? Since getType
method fails, it seems that it gets a different type than expected, maybe null? It's hard to tell anything more based on screenshots only :(
Turns out my
java.lang.Double cannot be cast to com.facebook.react.bridge.ReadableMap
was just a misleading error message. Double check the props you're passing to<SVG
-- I was accidentally passing an empty string""
for thefill
prop on an svg text element. For some reason that got converted to ajava.lang.Double
resulting in the confusing error message.
I took me a whole afternoon to figure out wtf was going on and it turned out, there was a stupid fill property has an empty string =.=
Hey @WoLewicki
How will we do it in this case?
const animation = useAnimatedProps(() => {
const fill = interpolateColor(
progress.value,
[0, 1],
[uncheckedBackgroundColor, checkedBackgroundColor]
);
const stroke = interpolateColor(
progress.value,
[0, 1],
[uncheckedBorderColor, checkedBorderColor]
);
return { fill, stroke };
});
const ellipseAnimatedProps = useAnimatedProps(() => { const coordinates = {cx: 50, cy: 50, rx: 40, ry: 40}; return { cx: coordinates.cx, cy: coordinates.cy, rx: coordinates.rx, ry: coordinates.ry, stroke: 'rgb(255,0,0)', fill: 'yellow', opacity: offset.value, strokeWidth: 2, }; } , [], createAnimatedPropAdapter( (props) => { if (Object.keys(props).includes('fill')) { props.fill = {type: 0, payload: processColor(props.fill)} } if (Object.keys(props).includes('stroke')) { props.stroke = {type: 0, payload: processColor(props.stroke)} } },
Wow a hidden gem! I was about to say that this solution should be put on the docs, but I checked and it's already there :). You know when you have this issue you don't really know inherently to look into the "createAnimatedPropAdapter" to get the solution but I'm glad I found it either way!
I am just wondering how to fix this error using
react-native
sAnimated
API?Here is an Example which is not working on the current
main
:java.lang.String cannot be cast to com.facebook.react.bridge.ReadableMap
const animation = React.useRef(new Animated.Value(0)); React.useEffect(() => { Animated.timing(animation.current, { toValue: 1, duration: 300, delay: 100, easing: Easing.out(Easing.quad), useNativeDriver: false, }).start(); }, []); return ( <SafeAreaView> <Svg width={40} height={40} viewBox="0 0 40 40" fill="none"> <AnimatedPath fill={animation.current.interpolate({ inputRange: [0, 0.4, 1], outputRange: ['#1F1F34', '#FFD761', '#FA9502'], })} d="M16.0489 0.927051C16.3483 0.00574017 17.6517 0.00574017 17.9511 0.927051L21.2658 11.1287C21.3996 11.5407 21.7836 11.8197 22.2168 11.8197H32.9434C33.9122 11.8197 34.3149 13.0593 33.5312 13.6287L24.8532 19.9336C24.5027 20.1883 24.3561 20.6396 24.4899 21.0517L27.8046 31.2533C28.104 32.1746 27.0495 32.9407 26.2658 32.3713L17.5878 26.0664C17.2373 25.8117 16.7627 25.8117 16.4122 26.0664L7.73419 32.3713C6.95048 32.9407 5.896 32.1746 6.19535 31.2533L9.51006 21.0517C9.64393 20.6396 9.49728 20.1883 9.14679 19.9336L0.468768 13.6287C-0.314945 13.0593 0.0878303 11.8197 1.05655 11.8197H11.7832C12.2164 11.8197 12.6004 11.5407 12.7342 11.1287L16.0489 0.927051Z" /> </Svg> </SafeAreaView> );
buschco@a1cbc20#diff-3ad04430c13b851d216fa0f686b4f9e4a7d013b50d492d9b27d969ccef669b74
Hey @buschco could you share an example of how you make it work with react-native's animated please I'm struggling to figure it out.
@MarlonAEC I spent went way too long on this example lol, hope it helps! https://snack.expo.dev/@oiver55/svg-reanimated-example-path-fill?platform=android
Hey @oiver555 I really love the effort you put into this example actually it helped me understand a bunch of things from react-native-reanimated
. Now the thing is that I was looking for a way to do it using this Animated
from react-native
NOT the one from react-native-reanimated
. Thanks for your example again it showed me a bunch of cool stuff I haven't tried with reanimited library! Super helpful!
@WoLewicki As you pointed out about adaptors.
I am facing one issue related to react-native-svg and reanimated. I am using SvgXml to dynamically render and change the svgs on UI thread. For that, I am using useAnimatedProps. But somehow it is not working. Does it have to do something with adaptor?
I have used following code :
import { SvgXml } from 'react-native-svg';
const AnimatedSVGXml = withAnimated(SvgXml); //withAnimated wraps SvgXml into class component
const svgXml = useSharedValue<string>(EmptySVG);
useAnimatedReaction(
() => {
return position;
},
(currentValue, previousValue) => {
if (currentValue !== previousValue) {
console.log('in useAnimatedReaction svg value', currentValue, previousValue);
//based on changes in position, I am updating svg
svgXml.value = currentValue;
}
},
);
const animatedSvgProps = useAnimatedProps(() => {
console.log('svgXml.value', svgXml.value);
// here I see that svgXml.value is updated. But not updated on screen. But if I remove svgXml.value and give the SVG directly it renders.
return {
xml: svgXml.value,
//xml : '<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>'
};
});
<AnimatedSVGXml animatedProps={animatedSvgProps} />
const ellipseAnimatedProps = useAnimatedProps(() => { const coordinates = {cx: 50, cy: 50, rx: 40, ry: 40}; return { cx: coordinates.cx, cy: coordinates.cy, rx: coordinates.rx, ry: coordinates.ry, stroke: 'rgb(255,0,0)', fill: 'yellow', opacity: offset.value, strokeWidth: 2, }; } , [], createAnimatedPropAdapter( (props) => { if (Object.keys(props).includes('fill')) { props.fill = {type: 0, payload: processColor(props.fill)} } if (Object.keys(props).includes('stroke')) { props.stroke = {type: 0, payload: processColor(props.stroke)} } },
Wow a hidden gem! I was about to say that this solution should be put on the docs, but I checked and it's already there :). You know when you have this issue you don't really know inherently to look into the "createAnimatedPropAdapter" to get the solution but I'm glad I found it either way!
This solved my problem. Thanks
@MarlonAEC I spent went way too long on this example lol, hope it helps! https://snack.expo.dev/@oiver55/svg-reanimated-example-path-fill?platform=android
Your example helped me fix my issue with Svg.Path. In my case I wanted to transition the fill
color when a condition is true
or false
.
I used useSharedValue
with interpolateColor
it worked perfectly on both android and iOS.
const animationFill = useSharedValue(1);
fill: interpolateColor(
animationFill.value,
[0, 0.2, 0.5, 1],
[randomColor1, randomColor2, randomColor3, randomColor4]
)
Thank you for taking the time to put this example together!
As pointed in the #1845 (comment), the best way to handle
fill
andstroke
props in by usingcreateAnimatedPropAdapter
which was made for this particular case, where props on the native side have different structure than in JS. Also, I changed thevalue
prop topayload
so it does not confusereanimated
babel plugin. YouranimatedProps
should look e.g. like this:const ellipseAnimatedProps = useAnimatedProps(() => { const coordinates = {cx: 50, cy: 50, rx: 40, ry: 40}; return { cx: coordinates.cx, cy: coordinates.cy, rx: coordinates.rx, ry: coordinates.ry, stroke: 'rgb(255,0,0)', fill: 'yellow', opacity: offset.value, strokeWidth: 2, }; } , [], createAnimatedPropAdapter( (props) => { if (Object.keys(props).includes('fill')) { props.fill = {type: 0, payload: processColor(props.fill)} } if (Object.keys(props).includes('stroke')) { props.stroke = {type: 0, payload: processColor(props.stroke)} } }, ['fill', 'stroke']));
This changed my svg form
` const animatedProps = useAnimatedProps( () => { const fillValue = interpolateColor( scrollY.value, [0, 150], [styleguide.colors.maiswhite, styleguide.colors.maismata500] ); return { fill: fillValue, }; }, [], createAnimatedPropAdapter( props => { if (Object.keys(props).includes("fill")) { props.fill = { type: 0, payload: props.fill }; } if (Object.keys(props).includes("stroke")) { props.stroke = { type: 0, payload: props.stroke }; } return props; }, ["fill", "stroke"] ) );
return ( <Animated.View style={[styles.backHeader, animatedStyle]}>
</Animated.View>`
Bug
After update from react-native-svg 12.1.0 to 13.0.0 I have a crash on android with the following stack trace
Unexpected behavior
Crash occurs since 13.0.0
Environment info
Run
react-native info
in your terminal and copy the results here. Also, include the precise version number of this library that you are using in the projectReact native info output:
Library version: 13.0.0
Steps To Reproduce
Issues without reproduction steps or code are likely to stall.
The project crashes at startup (no crash with 12.1.0)