React Native で Animated を使用してコンポーネントを作成しようとしています。このコンポーネントでは、プレスのポイントから円が拡大して画面全体を囲みます。
アイデアは、基本的に色のカルーセルがあるということです。
const colors = ['white', 'black', 'green', 'blue', 'red', 'pink'];
背景として色 0 で開始し、次に画面を押すと、色 1 の円が (何もないところから) 押した点から拡大し、画面全体を占めます。その時点で、アニメーションが完了すると、colorIndex
がインクリメントされ、アニメーション化された円が同時に消去されるため、シームレスに次の色 (現在は背景) に移動しました。(例: 現在、背景色として「黒」を使用しています)。
次に、もう一度押すと、プロセスが繰り返され、「緑」の円が拡大されて画面がいっぱいになり、緑が BG カラーになるように更新されます。
(アニメーションで何を探しているかを明確にするために、このGIFをチェックしてください(アイコンなどを除く))。
私はこれを Animated で試しています。次のようなコードは、メインの背景コンポーネント (TouchableHighlight) を押すと呼び出されます。
triggerSwipe(event) {
this.setState({ location: { x: event.nativeEvent.locationX, y: event.nativeEvent.locationY } });
Animated.timing(
this.state.diameter,
{ toValue: Dimensions.get('window').height * 2, duration: 500 },
).start(() => {
this.state.diameter.setValue(0);
this.setState({ colorIndex: this.state.colorIndex + 1 });
});
}
次に、render
関数で、配置された円コンポーネントの and を場所と等しくなるように設定し、 andleft
をtop
equalに設定し、(は数値ではなくアニメーション化されたオブジェクトであるため、機能しません)。absolute
width
height
diameter
borderRadius
diameter / 2.0
diameter
私が理解できないように見える2つの問題がここで起こっています(両方ともこの質問の下部に含まれるGIFに表示されています):
- すべてのアニメーションの前に黒いフラッシュがあります。TouchableHighlight コンポーネント全体をカバーします。そして常に黒です。私が着ている色は何でも。コンポーネントにハードコーディングされた黒はありません (!)。
- 位置は、円の中心ではなく、円の端 (より正確には、円が転写されている四角形) を決定します。円がプレスから外側に広がるように、円の中心を決定したいと思います。
#1は、すべてのコードがないと推論するのが本当に難しいと思います。そのため、完全なコンポーネント コードを以下に貼り付けます。私が望んでいる2番目のものは、もう少し概念的で、いじらずに理解しやすいものです。
円の中心の位置を主張する良い方法を考えられる人はいますか? 私が理解しているように、円の左/上の位置を直径の関数として常に更新する必要があるのではないかと心配しています ( left: location.x - diameter._value / 2
)。より良いアイデアはありますか?
完全なコンポーネント コードは次のとおりです。
import React from 'react';
import { TouchableHighlight, Animated } from 'react-native';
import { Dimensions } from 'react-native';
const colors = ['white', 'black', 'green', 'blue', 'red', 'pink'];
const color = index => colors[index % colors.length];
class ColorScape extends React.Component {
constructor(props) {
super(props);
this.state = {
colorIndex: 0,
location: { x: 0, y: 0 },
diameter: new Animated.Value(0)
};
}
triggerSwipe(event) {
this.setState({ location: { x: event.nativeEvent.locationX, y: event.nativeEvent.locationY } });
Animated.timing(
this.state.diameter,
{ toValue: Dimensions.get('window').height * 2, duration: 500 },
).start(() => {
this.state.diameter.setValue(0);
this.setState({ colorIndex: this.state.colorIndex + 1 });
});
}
render() {
const { colorIndex, diameter, location } = this.state;
const circleStyles = {
backgroundColor: color(colorIndex + 1),
width: diameter,
height: diameter,
borderRadius: diameter,
position: 'absolute',
zIndex: 2,
left: location.x,
top: location.y
};
return (
<TouchableHighlight
style={ {
flex: 1,
width: '100%',
height: '100%',
zIndex: 1,
backgroundColor: color(colorIndex)
} }
onPress={ (event) => this.triggerSwipe(event) }
>
<Animated.View
style={ circleStyles }
/>
</TouchableHighlight>
);
}
}
export default ColorScape;
現在の機能は次のとおりです (iPhone X シミュレーター)。