如何使用动画图像进行 React Native 倒计时?
How to do a React Native count down with animated images?
我正在尝试使用一些图像创建一个 React 原生动画作为倒计时,如下所示:
3 --> ease out down duration 1 second each case
2 --> ease out down
1 --> ease out down
我找到了一种使用 react animatable 来做到这一点的方法,但结果并不能说服我,如果有更好的方法,请告诉我。
我想每次我 运行 进入元素的新渲染时开始倒计时解决我遇到的问题的自然方法。
暂时没有用redux,可能以后会加上。
状态的属性:时间,当前开始时间尚未使用。
我所需要的只是我显示的图像在定义明确的动画中发生倒计时的效果。
我想快到了,但肯定有更好的方法来面对这个问题,任何建议都会受到欢迎,即使它是作为指南。我也尝试过使用 react-native-animate-number 但没有成功...
提前致谢
import React from 'react';
import util from '../utils.js';
import * as Animatable from 'react-native-animatable';
import {
View,
Dimensions,
Image,
StyleSheet
} from 'react-native';
const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;
const styles = StyleSheet.create({
mainOption: {
},
container: {
width: width,
height: height,
flex: 1,
justifyContent: 'center',
flexDirection: 'column',
alignItems: 'center'
}
});
const timeLapse = [
<Image source={require('../images/1.png')} key={util.uniqueId()}/>,
<Image source={require('../images/2.png')} key={util.uniqueId()}/>,
<Image source={require('../images/3.png')} key={util.uniqueId()}/>
];
export default class StartingGameCountDown extends React.Component {
constructor(props) {
super(props);
this.state = {
time: props.time,
currentTimeToBegin: props.currentTimeToBegin,
imagePosition: 0
};
}
componentWillReceiveProps(nextProps) {
const nextImage = this.state.imagePosition + 1;
this.setState({
...this.state,
letters: nextProps.time,
currentTimeToBegin: nextProps.currentTimeToBegin,
imagePosition: nextImage
});
}
render() {
return (
<View style={styles.container}>
<Animatable.View
ref='countDown'
duration={1000}
delay={0}
iterationCount={3}
animation="fadeOutDown"
style={styles.mainOption}>
{timeLapse[this.state.imagePosition]}
</Animatable.View>
</View>
);
}
}
好的,在查看文档后我发现可能正在使用顺序和计时可能是一个选项:
import React from 'react';
import {
Animated,
Text,
View,
Dimensions,
Image,
Easing,
StyleSheet
} from 'react-native';
const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;
let counter = 0;
const util = {
uniqueId: () => {
return counter++;
}
};
const styles = StyleSheet.create({
mainOption: {
},
container: {
width: width,
height: height,
top: -100,
flex: 1,
justifyContent: 'center',
flexDirection: 'column',
alignItems: 'center'
}
});
const timeLapse = [
require('../images/1.png'),
require('../images/2.png'),
require('../images/3.png')
];
export default class StartingGameCountDown extends React.Component {
constructor(props) {
super(props);
this.state = {
time: props.time,
countDown: new Animated.Value(0),
currentTimeToBegin: props.currentTimeToBegin,
quantity: 3,
sizes: [],
duration: props.duration,
animatedValues: [new Animated.Value(0), new Animated.Value(0), new Animated.Value(0)]
};
}
animations() {
let result = [];
state = this.state;
for(let i = 0; i < state.quantity; i++) {
//Start
result.push(Animated.timing(
state.countDown,
{
toValue: 0,
duration: 0
}
)
);
let parallel = [];
//Animate
for(let j = 0; j < state.quantity; j++) {
parallel.push(
Animated.timing(
state.animatedValues[j],
{
easing: Easing.bezier(.07,.42,.85,.5),
toValue: i === j ? 1 : 0,
duration: i === j ? state.duration : 0
}
)
);
}
//Stop
parallel.push(Animated.timing(
state.countDown,
{
easing: Easing.bezier(.07,.42,.85,.5),
toValue: 1,
duration: state.duration
}
)
);
result = [...result, Animated.parallel(parallel)];
}
return result;
}
componentDidMount() {
Animated.sequence(this.animations()).start();
}
shouldComponentUpdate(nextProps, nextState) {
//I don't to run lifecycle in any case by mistake here
return false;
}
createImagesAnimated() {
let transitionY = this.state.countDown.interpolate({
inputRange: [0, 1],
outputRange: [0, this.props.transition.y]
});
let result = [];
//What to be Animated
for(let i = 0; i < this.state.quantity; i++) {
let image = this.state.animatedValues[i].interpolate({
inputRange: [0, 0.5, 1],
outputRange: [0, 1, 0]
});
result.push(
<Animated.Image
key={util.uniqueId()}
source={timeLapse[i]}
style={{
//How to animate it
position: 'absolute',
opacity: image,
transform: [{
translateY: transitionY
}]
}}
/>
);
}
return result;
}
render() {
return (
<View style={styles.container}>
{this.createImagesAnimated()}
</View>
);
}
}
这将是组件的实现:
<CountDownComponent
transition={{y:200}}
duration={5000}
/>
这解决了我的问题我希望以后能找到更好的解决方案。
我正在尝试使用一些图像创建一个 React 原生动画作为倒计时,如下所示:
3 --> ease out down duration 1 second each case
2 --> ease out down
1 --> ease out down
我找到了一种使用 react animatable 来做到这一点的方法,但结果并不能说服我,如果有更好的方法,请告诉我。
我想每次我 运行 进入元素的新渲染时开始倒计时解决我遇到的问题的自然方法。
暂时没有用redux,可能以后会加上。 状态的属性:时间,当前开始时间尚未使用。
我所需要的只是我显示的图像在定义明确的动画中发生倒计时的效果。
我想快到了,但肯定有更好的方法来面对这个问题,任何建议都会受到欢迎,即使它是作为指南。我也尝试过使用 react-native-animate-number 但没有成功...
提前致谢
import React from 'react';
import util from '../utils.js';
import * as Animatable from 'react-native-animatable';
import {
View,
Dimensions,
Image,
StyleSheet
} from 'react-native';
const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;
const styles = StyleSheet.create({
mainOption: {
},
container: {
width: width,
height: height,
flex: 1,
justifyContent: 'center',
flexDirection: 'column',
alignItems: 'center'
}
});
const timeLapse = [
<Image source={require('../images/1.png')} key={util.uniqueId()}/>,
<Image source={require('../images/2.png')} key={util.uniqueId()}/>,
<Image source={require('../images/3.png')} key={util.uniqueId()}/>
];
export default class StartingGameCountDown extends React.Component {
constructor(props) {
super(props);
this.state = {
time: props.time,
currentTimeToBegin: props.currentTimeToBegin,
imagePosition: 0
};
}
componentWillReceiveProps(nextProps) {
const nextImage = this.state.imagePosition + 1;
this.setState({
...this.state,
letters: nextProps.time,
currentTimeToBegin: nextProps.currentTimeToBegin,
imagePosition: nextImage
});
}
render() {
return (
<View style={styles.container}>
<Animatable.View
ref='countDown'
duration={1000}
delay={0}
iterationCount={3}
animation="fadeOutDown"
style={styles.mainOption}>
{timeLapse[this.state.imagePosition]}
</Animatable.View>
</View>
);
}
}
好的,在查看文档后我发现可能正在使用顺序和计时可能是一个选项:
import React from 'react';
import {
Animated,
Text,
View,
Dimensions,
Image,
Easing,
StyleSheet
} from 'react-native';
const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;
let counter = 0;
const util = {
uniqueId: () => {
return counter++;
}
};
const styles = StyleSheet.create({
mainOption: {
},
container: {
width: width,
height: height,
top: -100,
flex: 1,
justifyContent: 'center',
flexDirection: 'column',
alignItems: 'center'
}
});
const timeLapse = [
require('../images/1.png'),
require('../images/2.png'),
require('../images/3.png')
];
export default class StartingGameCountDown extends React.Component {
constructor(props) {
super(props);
this.state = {
time: props.time,
countDown: new Animated.Value(0),
currentTimeToBegin: props.currentTimeToBegin,
quantity: 3,
sizes: [],
duration: props.duration,
animatedValues: [new Animated.Value(0), new Animated.Value(0), new Animated.Value(0)]
};
}
animations() {
let result = [];
state = this.state;
for(let i = 0; i < state.quantity; i++) {
//Start
result.push(Animated.timing(
state.countDown,
{
toValue: 0,
duration: 0
}
)
);
let parallel = [];
//Animate
for(let j = 0; j < state.quantity; j++) {
parallel.push(
Animated.timing(
state.animatedValues[j],
{
easing: Easing.bezier(.07,.42,.85,.5),
toValue: i === j ? 1 : 0,
duration: i === j ? state.duration : 0
}
)
);
}
//Stop
parallel.push(Animated.timing(
state.countDown,
{
easing: Easing.bezier(.07,.42,.85,.5),
toValue: 1,
duration: state.duration
}
)
);
result = [...result, Animated.parallel(parallel)];
}
return result;
}
componentDidMount() {
Animated.sequence(this.animations()).start();
}
shouldComponentUpdate(nextProps, nextState) {
//I don't to run lifecycle in any case by mistake here
return false;
}
createImagesAnimated() {
let transitionY = this.state.countDown.interpolate({
inputRange: [0, 1],
outputRange: [0, this.props.transition.y]
});
let result = [];
//What to be Animated
for(let i = 0; i < this.state.quantity; i++) {
let image = this.state.animatedValues[i].interpolate({
inputRange: [0, 0.5, 1],
outputRange: [0, 1, 0]
});
result.push(
<Animated.Image
key={util.uniqueId()}
source={timeLapse[i]}
style={{
//How to animate it
position: 'absolute',
opacity: image,
transform: [{
translateY: transitionY
}]
}}
/>
);
}
return result;
}
render() {
return (
<View style={styles.container}>
{this.createImagesAnimated()}
</View>
);
}
}
这将是组件的实现:
<CountDownComponent
transition={{y:200}}
duration={5000}
/>
这解决了我的问题我希望以后能找到更好的解决方案。