React Native flexDirection animation - reactjs

I am trying to to an animation which basically changes flexDirection of a view. Check the code
state = {
fadeAnim: new Animated.Value(0),
flex_direction_anim: new Animated.Value("column")
}
componentDidMount() {
Animated.timing(
this.state.fadeAnim,
{
toValue: 1,
duration: 2000
}
).start();
setTimeout(() => {
Animated.timing(
this.state.flex_direction_anim, {
toValue: "row",
duration: 2000
}
)
}, 5000)
}
In above code i have two animations set, fade animation is working fine, but the other animation just throws following error.
I am not sure what i am doing wrong here, may be this kind of animation is not supported in React-Native.
I have also used react-native-animatable library, and also opened an issue here
Any documentation or lead will be very helpful,
Thanks

Related

Inconsistent delay time for executing code

I'm trying to write some code to play animations with the help of the react package framer-motion:
import React from "react";
import './Line.css';
import { motion, useAnimation } from 'framer-motion';
export const Line = ({speed}) => {
const [goingRight, setGoingRight] = React.useState(false);
const [delay, setDelay] = React.useState(1);
const [oldTime, setOldTime] = React.useState(new Date().getTime());
const controls = useAnimation()
React.useEffect(() => {
controls.start({
x: 280,
transition: { delay: 0, duration: speed, type: 'tween', ease: 'linear' }
})
}, [])
const start = async () => {
setDelay((new Date().getTime()) - oldTime);
setOldTime(new Date().getTime());
await setGoingRight(!goingRight);
if (goingRight) {
await controls.start({
x: 280,
transition: { delay: 0, duration: speed, type: 'tween', ease: 'linear' }
})
} else {
await controls.start({
x: 0,
transition: { delay: 0, duration: speed, type: 'tween', ease: 'linear' }
})
}
}
return (
<>
{delay}
<div className='outer'>
<motion.div className='ball'
animate={controls}
onAnimationComplete={() => start()}
/>
<div className='line'/>
</div>
</>
)
}
This component renders a horizontal line and a circle that sits on that line, the circle starts at the left side of the line and is animated to the right. After that, another animation is made to move the circle back to the left and then the cycle continues.
Each animation takes as long as the speed property (in seconds).
I'm also displaying the delay state variable which does the appropriate math to so determine how many milliseconds the most recent animation took since the last animation.
Here's my problem, let's say I render this component with a speed property of 1. In a perfect world, delay would always = 1000, but of course, there's some time loss for executing the code in the start() function so delay usually = 1017 instead. That would be fine because I could account for the difference, but strangely, delay is sometimes exactly 1000 instead (around 1 in every 4 animations it seems, but it's not consistent).
I need these animation times to be precise and this is too much of a deviation for what I need and I can't seem to figure out how to fix it. I have a suspicion this might be just be the nature of doing all this in real time and that it may be an unsolvable problem, but I figured I'd ask in case anyone has found themselves in a scenario like this before.
Instead of using multiple animation that are run after another, I've tried just using one infinitely repeating animation like this:
controls.start({
x: 280,
transition: { delay: 0, duration: speed, type: 'tween', ease: 'linear' repeat: Infinity, repeatType: 'reverse', }
})
The problem with doing this is that I need code to run after the circle hits the end of the line every time, which before I was using onAnimationComplete to accomplish, but onAnimationComplete seems to only be triggered when the entire animation completes, not also when it repeats

why would changes to the Ref object trigger rerender in this code

as shown in the react-native animation demo on https://reactnative.dev/docs/animated
const fadeAnim = useRef(new Animated.Value(0)).current // Initial value for opacity: 0
React.useEffect(() => {
Animated.timing(
fadeAnim,
{
toValue: 1,
duration: 10000,
}
).start();
}, [fadeAnim])
return (
<Animated.View // Special animatable View
style={{
...props.style,
opacity: fadeAnim, // Bind opacity to animated value
}}
>
{props.children}
</Animated.View>
);
}
the changes to the fadeAnim would trigger rerender of the component, which I don't understand.
the react documentation never mentions the ref object is part of state either.
am I missing something?
Im not sure but I think it will still work even if you remove fadeAnim in the dependency of useEffect. I never tried using refs as a dependency of hooks before and it works as expected.

How to translateX, translateY to a certain coordinate rather than a relative point?

My question is about using translateX and translateY in react and/or react-native animations, to animate an object to a certain point.
These two transformations move an object relative to the existing point.
But for the scenario, the existing coordinate is not important and I want to assure the object moves to a certain point wherever it may exist in the screen.
Additional limitation is, I can not animate styles top, bottom, left and right because in react-native, if we animate these styles then we can not use the useNativeDriver={true} directive which causes performance problems.
You can use the onLayout prop to get position (relative to parent) and height/width on any View component.
Something like this should work. You might need to get position of more parent View components, depending on your current structure.
componentDidMount() {
this.animatedValue = new Animated.Value(0);
}
animate() {
const { parentYPosition } = this.state;
Animated.Timing(this.animatedValue, {
toValue: FINAL_POSITION - parentYPosition
}).start();
}
render() {
return (
<View
onLayout={event => {
const { y } = event.nativeEvent.layout;
this.setState({parentYPosition: y})
}}
>
<Animated.View
style={{
position: 'absolute',
top: 0,
transform: [
{
translateY: this.animatedValue
}
/>
/>
);
}
https://facebook.github.io/react-native/docs/view#onlayout

How to scale the size of a button when the user holds down in Animated React / React Native?

I'm trying to create some code that increases the size of a button when the user holds it down then reverts back to the initial size when released.
I'm relatively new to React/RN and have searched tons of websites to find the result, but can't seem to find anything.
I can't tell whether I should be using PanResponder here or not. I also tried using Animated.timing, but the timing is hard-coded & not bound to the length of time that the user holds down the button. I tried Animated.spring, but again that's not bound to length of time that the user holds the button down.
I'll post a quick gif that replicates what I'm trying to go for.
https://imgur.com/a56pSQl
Here's what I have so far:
this.scaleAnimation = new Animated.value(3)
handlePress = () => {
Animated.spring(this.scaleAnimation, {
toValue: 4,
friction: 2,
tension: 160
}).start()
}
render() {
const pauseStyle = {
transform: [
{ scale: this.scaleAnimation }
]
}
return (
<TouchableWithoutFeedback onPress={this.handlePress}>
<Animated.View style={[ pauseStyle ]}>
<Ionicons name="md-pause" />
</Animated.View>
</TouchableWithoutFeedback>
)
}
Any takes are greatly appreciated :D
Please find the detailed answer with code snippets.
Add this to constructor of component
this.handlePressIn = this.handlePressIn.bind(this);
this.handlePressOut = this.handlePressOut.bind(this);
this.animatedValue = new Animated.Value(1);
This method is for scaling button with animation when button gets pressed
handlePressIn() {
Animated.spring(this.animatedValue, {
toValue: 3,
friction: 3,
tension: 40
}).start();
}
This method is for resetting button to its initial scale with animation when touch gets released
handlePressOut() {
Animated.spring(this.animatedValue, {
toValue: 1,
friction: 3,
tension: 40
}).start();
}
Render method
render() {
const animatedStyle = {
transform: [{ scale: this.animatedValue }]
}
return (
<TouchableWithoutFeedback
onPressIn={this.handlePressIn}
onPressOut={this.handlePressOut}
>
<Animated.View style={animatedStyle}>
<Text style={styles.text}>Press Me</Text>
</Animated.View>
</TouchableWithoutFeedback>
);
}
You can use different types of animations. Please find the link for reference:
https://facebook.github.io/react-native/docs/animated#configuring-animations

Animate paddingLeft React Native

i am trying animate paddingLeft property on IOS it isn't work
state = {
paddingAnimation: new Animated.Value(40),
};
animate(){
let {paddingAnimation} = this.state;
Animated.timing( paddingAnimation, { toValue: 100, duration: 100}).start();
}
In Render
<AnimatedInputText style={[styles.search, {margin: paddingAnimation}]}>
It works on Android but not in IOS.
Any solutions ?
You want to Animate padding left then use paddingLeft not margin example
import {
View,
Text,
StyleSheet,Animated,
} from "react-native";
this.state = {paddingAnimation: new Animated.Value(40),}
componentWillMount()
{
Animated.timing( this.state.paddingAnimation, { toValue: 100, duration: 1000}).start();
}
render() {
return (
<View style={styles.container}>
<Animated.Text style={[{paddingLeft: this.state.paddingAnimation}]}>
LoginForm
</Animated.Text>
</View>
});
it will work in both Animated.Text To animate .
Animated exports the following animatable components using the above wrapper:
Animated.Image
Animated.ScrollView
Animated.Text
Animated.View
if you want to create your own use this
Animated.createAnimatedComponent()

Resources