Reputation: 339
I want to create a circular animation like a wave and i found that code on the internet. And i converted and changed it with react hooks but then this code does not work correctly. Where is my mistake?
const constructAnimations = [...Array(COUNT).keys()].map(() => initialPhase);
export default function SearchAnimation() {
const [stateAnimations, setStateAnimations] = useState(constructAnimations);
useEffect(() => {
const actions = Array(COUNT).fill(
keyframes({
values: [initialPhase, { scale: 2, opacity: 0 }],
duration: DURATION,
loop: Infinity,
yoyo: Infinity,
})
);
stagger(actions, DURATION / COUNT).start((animations) => {
setStateAnimations({ animations });
});
}, []);
return (
<View style={styles.container}>
{[stateAnimations].map(({ opacity, scale }, index) => {
return (
<Animated.View
key={index}
style={[
styles.circle,
{
transform: [{ scale }],
opacity,
},
]}
/>
);
})}
<View style={styles.midCircle}>
<FontAwesome name="phone" style={styles.icon} />
<Text style={styles.text}>Searching</Text>
</View>
</View>
);
}
Also the error message:
TypeError: undefined is not an object (evaluating 'value.getValue')
This error is located at:
in RCTView (at View.js:34)
in View (at createAnimatedComponent.js:165)
in AnimatedComponent (at createAnimatedComponent.js:215)
in ForwardRef(AnimatedComponentWrapper) (at SearchAnimation.js:33)
in RCTView (at View.js:34)
Upvotes: 0
Views: 1219
Reputation: 15462
There are a couple of problems I've found.
The first is that the class based example you linked maps over the stateAnimations
array, but you map over [stateAnimations]
.
So since stateAnimations
is already an array you don't need to
surround it with another array. If you fix this the error you posted in your question goes away.
I also found that the working class-based example uses version 8.6.2
of popmotion
and the code in the example apparently doesn't work anymore for version 9+
.
So after downgrading to 8.6.2
the following code worked for me:
import React, { useState, useEffect } from "react";
import { Animated, Text, View, StyleSheet } from "react-native";
import { keyframes, stagger, tween } from "popmotion";
import { FontAwesome } from "@expo/vector-icons";
const COUNT = 4;
const DURATION = 5000;
const initialPhase = { scale: 0, opacity: 1 };
const constructAnimations = [...Array(COUNT).keys()].map(() => initialPhase);
export default function SearchAnimation() {
const [stateAnimations, setStateAnimations] = useState(constructAnimations);
useEffect(() => {
const actions = Array(COUNT).fill(
keyframes({
values: [initialPhase, { scale: 2, opacity: 0 }],
duration: DURATION,
loop: Infinity,
yoyo: Infinity,
})
);
stagger(actions, DURATION / COUNT).start((animations) => {
setStateAnimations(animations);
});
}, []);
return (
<View style={styles.container}>
{stateAnimations.map(({ opacity, scale }, index) => {
return (
<Animated.View
key={index}
style={[
styles.circle,
{
transform: [{ scale }],
opacity,
},
]}
/>
);
})}
<View style={styles.midCircle}>
<FontAwesome name="phone" style={styles.icon} />
<Text style={styles.text}>Searching</Text>
</View>
</View>
);
}
const getCircle = (radius, backgroundColor = "gold") => ({
backgroundColor,
width: radius * 2,
height: radius * 2,
borderRadius: radius,
position: "absolute",
});
const styles = StyleSheet.create({
icon: {
color: "white",
fontSize: 42,
marginBottom: 5,
},
text: {
color: "white",
fontSize: 18,
},
circle: getCircle(100),
midCircle: {
...getCircle(75),
alignItems: "center",
justifyContent: "center",
},
container: {
flex: 1,
alignItems: "center",
backgroundColor: "#fff",
justifyContent: "center",
},
});
Upvotes: 3