我正在尝试为ReactJS原生中的组件设置动画,以便它以循环方式围绕某个点连续旋转。基本上,我需要一个不断增加的计时器,我可以用来将X,Y坐标设置为{x: r * Math.sin(timer), y: r * Math.cos(timer)}
我发现这个指南有一些关于插值的非常有用的信息,但我仍然没有取得任何成功:
http://browniefed.com/react-native-animation-book/INTERPOLATION.html
如何像这样更新组件的位置?
奖金问题:如何让动画连续?
答案 0 :(得分:5)
由于react-native插值不支持函数回调,我做了一个辅助函数:
function withFunction(callback) {
let inputRange = [], outputRange = [], steps = 50;
/// input range 0-1
for (let i=0; i<=steps; ++i) {
let key = i/steps;
inputRange.push(key);
outputRange.push(callback(key));
}
return { inputRange, outputRange };
}
将动画应用于translateX和translateY:
transform: [
{
translateX:
this.rotate.interpolate(
withFunction( (value) => Math.cos(Math.PI*value*2) * radius )
)
},
{
translateY:
this.rotate.interpolate(
withFunction( (value) => Math.sin(Math.PI*value*2) * radius )
)
},
]
视觉结果:
为了使动画连续,我做了类似的事情:
rotate = new Animated.Value(0);
componentDidMount() {
setInterval( () => {
let step = 0.05;
let final = this.rotate._value+step;
if (final >= 1) final = 0;
this.rotate.setValue(final);
}, 50);
}
答案 1 :(得分:1)
我最终找到了一种方法来做到这一点,虽然它并不理想,我会欣赏任何其他输入。这是我的代码:
class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
rotation: new Animated.Value(0),
pos: new Animated.ValueXY()
}
}
componentDidMount() {
this.animate(10000);
}
animate(speed) {
Animated.parallel([
Animated.timing(this.state.rotation, {
toValue: 360,
duration: speed,
easing: Easing.linear
}),
Animated.timing(this.state.pos, {
toValue: {x: 360, y: 360},
duration: speed,
easing: Easing.linear,
extrapolate: 'clamp'
})
]).start(() => {
// Cycle the animation
this.state.rotation.setValue(0);
this.state.pos.setValue({x: 0, y: 0});
this.animate(speed);
});
}
render() {
let range = new Array(360);
for (let i = 0; i < 360; i++) {
range[i] = i;
}
var radius = 51,
offset = 40;
return (
<View style={this.props.style}>
<Animated.View style={{position: 'absolute', transform: [
// Map the inputs [0..360) to x, y values
{translateX: this.state.pos.x.interpolate({
inputRange: range,
outputRange: range.map(i => offset + radius * Math.cos(i * Math.PI / 180))
})},
{translateY: this.state.pos.y.interpolate({
inputRange: range,
outputRange: range.map(i => offset - radius * Math.sin(i * Math.PI / 180))
})},
{rotate: this.state.rotation.interpolate({
inputRange: [0, 360],
outputRange: ['360deg', '0deg']
})}
]}}>
<Image source={require('image.png')}/>
</Animated.View>
</View>
)
}
}
基本上,我使用插值函数将Animated.Value
pos
映射到我所有360度函数的结果。我认为这可以通过使用一种map函数而不是insertlate函数来改进。有谁知道是否有一个?