ReactJS:AnimationValue.interpolate 用于 sin 和 cos
ReactJS: AnimationValue.interpolate for sin and cos
我正在尝试为 ReactJS 原生组件设置动画,使其以圆形方式围绕一个点连续运行。基本上,我需要一个不断增加的计时器,我可以用它来将 X、Y 坐标设置为 {x: r * Math.sin(timer), y: r * Math.cos(timer)}
我找到了这个指南,其中包含一些关于插值的非常有用的信息,但我仍然没有取得任何成功:
http://browniefed.com/react-native-animation-book/INTERPOLATION.html
如何像这样更新组件的位置?
附加问题:如何使动画连续?
我最终想出了一个方法来做到这一点,虽然它并不理想,但我会很感激任何其他输入。这是我的代码:
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 度结果。我认为这可以通过使用一种映射函数而不是插值函数来改进。有谁知道有没有?
由于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);
}
我正在尝试为 ReactJS 原生组件设置动画,使其以圆形方式围绕一个点连续运行。基本上,我需要一个不断增加的计时器,我可以用它来将 X、Y 坐标设置为 {x: r * Math.sin(timer), y: r * Math.cos(timer)}
我找到了这个指南,其中包含一些关于插值的非常有用的信息,但我仍然没有取得任何成功:
http://browniefed.com/react-native-animation-book/INTERPOLATION.html
如何像这样更新组件的位置?
附加问题:如何使动画连续?
我最终想出了一个方法来做到这一点,虽然它并不理想,但我会很感激任何其他输入。这是我的代码:
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 度结果。我认为这可以通过使用一种映射函数而不是插值函数来改进。有谁知道有没有?
由于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);
}