How to spin an image infinitely in React Native - javascript

I'm trying to spin an image infinitely, a rotating disk.
I checked using animated or the react-native-animatable. They've got duration and timing, how do I rotate without putting a time or angle of spin to it.
const handleAnimation = () => {
Animated.timing(rotateAnimation, {
toValue: 1,
duration: 72000,
useNativeDriver: false,
}).start(() => {
rotateAnimation.setValue(0);
});
};
<TouchableOpacity onPress={async () => handleAnimation()}>
<Animated.Image
style={{
width: 300,
height: 300,
transform: [{ rotate: interpolateRotating }]
}}
source={abcd} >
</Animated.Image>
</TouchableOpacity>

Try adding the Animated.timing in a Animated.loop
Animated.loop(
Animated.timing(rotateAnimation, {
toValue: 1,
duration: 72000,
useNativeDriver: false,
})
).start();

Related

How can i make a child animation happen every time the parent animation is beginning using framer motion & react

I'm trying to make a squeezing bubble animation on repeat, using framer motion & react, but I cant make the squeeze animation happen every time the movement animation is beginning.
instead only the first time the animations run it works but after that only the movement animation repeats itself, if I try to repeat the squeeze animation it just gets out of order
import React from "react";
import styled from "styled-components";
import { motion } from "framer-motion";
const Bubble = () => {
const shapeVariants = {
hidden: {
height: 450,
width: 50,
},
visible: {
height: 250,
width: 250,
transition: {
type: "spring",
bounce: 1,
stiffness: 700,
ease: "easeIn",
},
},
};
const MoveVariants = {
hidden: {
y: 1300,
},
visible: {
y: -280,
transition: {
duration: 2,
ease: "easeIn",
repeat: Infinity,
},
},
};
return (
<motion.div variants={MoveVariants} initial={"hidden"} animate={"visible"}>
<RoundDiv
onAnimationComplete={(definition) => console.log(definition)}
variants={shapeVariants}
/>
</motion.div>
);
};
const RoundDiv = styled(motion.div)`
height: 250px;
width: 250px;
background-color: #05386b;
border-radius: 50%;
`;
export default Bubble;
You just needed to add to your shapeVariants transition to get them to sync up.
import React from "react";
import styled from "styled-components";
import { motion } from "framer-motion";
const Bubble = () => {
const shapeVariants = {
hidden: {
height: 450,
width: 50,
},
visible: {
height: 250,
width: 250,
transition: {
type: "spring",
bounce: 1,
stiffness: 700,
ease: "easeIn",
duration: 2, /* new */
repeat: Infinity, /* new */
},
},
};
const MoveVariants = {
hidden: {
y: 1300,
},
visible: {
y: -280,
transition: {
duration: 2,
ease: "easeIn",
repeat: Infinity,
},
},
};
return (
<motion.div
variants={MoveVariants}
initial={"hidden"}
animate={"visible"}
>
<RoundDiv
onAnimationComplete={(definition) => console.log(definition)}
variants={shapeVariants}
/>
</motion.div>
);
};
const RoundDiv = styled(motion.div)`
height: 250px;
width: 250px;
background-color: #05386b;
border-radius: 50%;
`;
export default Bubble;
I would also recommend using originX and originY to manipulate the spring transition on the bubble otherwise it will animate the bounce based on the top left corner. I would use percentage values such as originX: "50%" but it depends on the effect you are looking for.
The cascading animation in framer-motion is powered by the variant being propagated through the children.
You are running into this setback because you are only animating to the `visible variant once. Thus the variant propagation only happens once.
Potential Solutions
Dumb solution: include a duration into the shapeVariant and make it also repeat then manually time your animation to where you need it. This isn't optimal because you probably want your bubble animation to be type spring?
const shapeVariants = {
hidden: {
height: 450,
width: 50,
},
visible: {
height: 250,
width: 250,
transition: {
type: "spring",
bounce: 1,
stiffness: 700,
ease: "easeIn",
duration: 2,
repeat: Infinity
},
},
};
Alternatively you could control your animation with an effect that would use setTimeout or something to change the variant of the parent over and over to get the cascading effect

How to animate a button from middle of the screen to bottom of the screen

I have implemented a floating button(TouchableOpacity)in react native. I was able to show and hide the button as per the scrolling position. Instead of showing and hiding i want to move button completely out of the screen(bottom)
when the scrollview scrolls up and when it scroll down i want to move the button up from the bottom of screen. I want to achieve this using smooth animation.
Below is the code i have used to create floating button and show and hide while scrolling.
//For Handling button show and hide for the scroll position.
handleScroll = (event: any) => {
const { animatedOpacityValue, showBlueButton } = this.state;
const scrollPosition = event.nativeEvent.contentOffset.y;
console.log('Scroll Position:', scrollPosition);
if (scrollPosition > 0 && scrollPosition < 400) {
Animated.timing(this.state.animatedOpacityValue, {
toValue: 1,
duration: 5,
useNativeDriver: true,
}).start(() => this.setState({ showBlueButton: true }));
} else if (scrollPosition > 400 && showBlueButton) {
Animated.timing(this.state.animatedOpacityValue, {
toValue: 0,
duration: 5,
useNativeDriver: true,
}).start(() => this.setState({ showBlueButton: false }));
}
};
// Render Method
<ScrollView
style={styles.scrollViewStyles}
contentContainerStyle={{ paddingBottom: 330 }}
contentInset={{
top: 10,
bottom: Platform.OS === 'ios' ? 0 : 100,
}}
onScroll={this.handleScroll}
scrollEventThrottle={16}>
<CardView
onSymptomLog={() => {
this.state.navigation.push('SymptomLogs');
}}
/>
<TodaySymptomsCard
showBlueView={this.state.showBlueView}
reminderTime={'5:40 PM'}
symptomsCount={0}
onEditAction={() => {
this.state.navigation.push('SetRemainder');
}}
/>
{this.state.showBlueButton && (
<TouchableOpacity
style={{
backgroundColor: AppColors.DARK_BLUE_BUTTON_COLOR,
top: -50,
alignItems: 'center',
width: 150,
height: 50,
borderRadius: 28,
justifyContent: 'center',
left: '30%',
shadowOffset: { width: 1, height: 1 },
shadowColor: 'grey',
shadowOpacity: 2.0,
}}>
<Text style={{ color: AppColors.WHITE, fontSize: 20 }}>
+ Symptoms
</Text>
</TouchableOpacity>
)}
<WearableStatus
batteryPercentage="80%"
batteryStatus={true}
/>
<Support
address="sdfsd fsdfsdfsdf"
phone="122-534-3445"
email="sdfsdfdsfsd#mgail.com"
/>
</ScrollView>
Any help is appreciated. Thanks.
Call these functions based on your scrollPosition
const driver = Animated.value(0) //1 if the button should be shown by default
const fadeIn = () => {
Animated.timing(driver, {
toValue: 1,
duration: 500,
useNativeDriver: true
}).start()
}
const fadeout = () => {
Animated.timing(driver, {
toValue: 0,
duration: 500,
useNativeDriver: true
}).start()
}
Wrap your TouchableOpacity in an <Animated.View> and style it like this:
Style={{
transform: [{
translateY: driver.interpolate({
inputRange: [0, 1],
outputRange: [startingYPosition, EndingYposition]
})
}]
}}
Lets say that the positionY of your button is 700 when visible, then the values of outputRange would be [0, 700]

How to scroll new page to top on load on click?

I'm using barba.js to fade new pages in. Code must be placed between the barba wrapper div. When I click a link to a new page though, the new page fades in at the same position as the previous page was in. So if the user clicks a link, the new page is loading in near , which I don't want.
How can I get the new page to load in at the top?
I found the answer on stack about scrollRestoration function but I still don't understand how to make this work.
Could somebody help me to compile the js code below, add some css or html to fix this issue?
$(window).scrollTop(0);
if ('scrollRestoration' in history) {
history.scrollRestoration = 'manual';
}
function delay(n) {
n = n || 2000;
return new Promise((done) => {
setTimeout(() => {
done();
}, n);
});
}
function pageTransition() {
var tl = gsap.timeline();
tl.to(".animate-this", {
duration: .2, opacity: 0, delay: 0, y: 30, //scale:0, delay: 0.2,
});
tl.to(".animate-this", {
duration: 0, opacity: 0, delay: 0, scale:0, //scale:0, delay: 0.2,
});
tl.fromTo(".loading-screen", {width: 0, left: 0}, {
duration: 1,
width: "100%",
left: "0%",
ease: "expo.inOut",
delay: 0.3,
});
tl.to("#svg-1", {
duration: 1, opacity: 0, y: 30, stagger: 0.4, delay: 0.2,
});
tl.to(".loading-screen", {
duration: 1,
width: "100%",
left: "100%",
ease: "expo.inOut",
delay: 0, //CHANGE TIME HERE END TRANS
});
tl.set(".loading-screen", { left: "-100%", });
tl.set("#svg-1", { opacity: 1, y: 0 });
}
function contentAnimation() {
var tl = gsap.timeline();
tl.from(".animate-this", { duration: .5, y: 30, opacity: 0, stagger: 0.4, delay: 0.2 });
}
$(function () {
barba.init({
sync: true,
transitions: [
{
async leave(data) {
const done = this.async();
pageTransition();
await delay(2500);
done();
},
async enter(data) {
contentAnimation();
},
async once(data) {
contentAnimation();
},
},
],
});
});
Have a look:
https://pasteboard.co/Ja33erZ.gif
Here also a codepen to check my issue (html,css):
https://codepen.io/cat999/project/editor/AEeEdg
scrollRestoration shouldn't be necessary, this can be done by resetting scroll position during the transition:
tl.fromTo(".loading-screen", {width: 0, left: 0}, {
duration: 1,
width: "100%",
left: "0%",
ease: "expo.inOut",
delay: 0.3,
onComplete: function() {
window.scrollTo(0, 0);
}
});
Working example here: https://codepen.io/durchanek/project/editor/ZWOyjE
This should be what you're looking for:
barba.hooks.enter(() => {
window.scrollTo(0, 0);
});
(can be found in the docs)

Framer-motion, delay rotateY while animating x

I'm working with Framer-motion and i'm trying to find a way to delay the the animation of rotateY while the x animates to a specific position then start the rotateY.
Is this possible in Framer motion ?
Example:
const variants = {
flip: {
rotateY: 0,
x: -20,
scale: 1,
transition: {
ease: "easeInOut",
duration: 1.2
}
},
hidden: {
rotateY: 180,
x: 150,
scale: 0.5,
transition: {
ease: "easeInOut",
duration: 1
}
}
};
You can configure a transition per property. This allows you to add the necessary delay to rotateY:
const duration = 1.2;
const variants = {
flip: {
rotateY: 0,
x: -20,
scale: 1,
transition: {
ease: "easeInOut",
duration,
rotateY: {
delay: duration,
duration
}
}
},
hidden: {
rotateY: 180,
x: 150,
scale: 0.5,
transition: {
ease: "easeInOut",
duration,
rotateY: {
delay: duration,
duration
}
}
}
};
See this CodeSandbox.
#amann's post above didn't wor for me in Sep 2020 v2.65
I had to update all relevant properties in the transition to ensure they ran in succession:
transition: {
x: {
ease: "easeInOut",
duration: duration
},
rotateY: {
duration: duration,
delay: duration
}
}
Full example:
import * as React from "react";
import { motion } from "framer-motion";
import styled from "styled-components";
const duration = 1.2;
const variants = {
flip: {
rotateY: 180,
x: 150,
transition: {
x: {
ease: "easeInOut",
duration: duration
},
rotateY: {
duration: duration,
delay: duration
}
}
},
hidden: {
rotateY: 0,
x: -20,
transition: {
x: {
ease: "easeInOut",
duration: duration
},
rotateY: {
duration: duration,
delay: duration
}
}
}
};
const Box = styled(motion.div)`
background: white;
border-radius: 30px;
width: 150px;
height: 150px;
`;
export const Example = (props) => {
return (
<motion.div
initial={false}
animate={props.toggle ? "flip": "hidden"}
>
<Box variants={variants} />
</motion.div>
)
}
Codesandbox Demo
You can give specific values for each transition. Therefore, you can control them individually like so:
transition={{
rotate: { duration: 1 },
scale: { duration: 0.2 }
}}

Can not find Variable in react-native

I am trying to build an app in react native and keep having an error titled Cannot find variable: opacity in a feature that should fade an image in and then fade an image out depending on the user pressing a button.
I have tried multiple things such as using the let operator and trying to change where the code is located in the class.
here is the code for the button and animation
import React, { Component } from "react";
import {
Image,
Animated,
Easing,
StyleSheet,
TouchableWithoutFeedBack
} from "react-native";
const styles = StyleSheet.create({
info: {
// for info button
height: 50,
width: 50,
flex: 1,
position: "absolute",
left: 315,
bottom: -675
}
});
class Info extends Component<Props> {
state = { opacity: new Animated.Value(0) };
infoScale = opacity.interpolate({
inputRange: [0, 1],
outputRange: [0.85, 1],
});
transformStyle = {
...styles.image,
transform: [{ opacity: infoScale }]
};
render() {
return (
<TouchableWithoutFeedBack
onPressIn={() => {
scaleValue.setValue(0);
Animated.timing(opacity, {
toValue: 1,
duration: 250,
easing: Easing.linear,
useNativeDriver: true
}).start();
}}
onPressOut={() => {
Animated.timing(opacity, {
toValue: 0,
duration: 100,
easing: Easing.linear,
useNativeDriver: true
}).start();
}}
>
<Image
source={require("../assets/images/info2.png")}
style={styles.info}
resizeMode="contain"
/>
<Animated.View style={transformStyle}>
<Image source={require("../assets/images/iPhoneTimeTreeInfo.png")} />
</Animated.View>
</TouchableWithoutFeedBack>
);
}
}
export default Info;
opacity in Animated.timing should be this.state.opacity
import React, { Component } from "react";
import {
Image,
Animated,
Easing,
StyleSheet,
TouchableWithoutFeedBack
} from "react-native";
const styles = StyleSheet.create({
info: {
// for info button
height: 50,
width: 50,
flex: 1,
position: "absolute",
left: 315,
bottom: -675
}
});
class Info extends Component<Props> {
state = { opacity: new Animated.Value(0) };
infoScale = this.state.opacity.interpolate({
inputRange: [0, 1],
outputRange: [0.85, 1],
});
transformStyle = {
...styles.image,
transform: [{ opacity: infoScale }]
};
render() {
return (
<TouchableWithoutFeedBack
onPressIn={() => {
scaleValue.setValue(0);
Animated.timing(this.state.opacity, {
toValue: 1,
duration: 250,
easing: Easing.linear,
useNativeDriver: true
}).start();
}}
onPressOut={() => {
Animated.timing(this.state.opacity, {
toValue: 0,
duration: 100,
easing: Easing.linear,
useNativeDriver: true
}).start();
}}
>
<Image
source={require("../assets/images/info2.png")}
style={styles.info}
resizeMode="contain"
/>
<Animated.View style={transformStyle}>
<Image source={require("../assets/images/iPhoneTimeTreeInfo.png")} />
</Animated.View>
</TouchableWithoutFeedBack>
);
}
}
export default Info;

Categories