React Native - 屏幕上的随机视图(圆形)
React Native - Randomized view (Circle) on the screen
我是 React Native 的新手。我正在尝试构建一个需要在屏幕上随机移动的视图(圆圈)的功能。有人可以帮我从哪里开始吗?提前致谢。
更新:我现在正在尝试创建一个可拖动的组件,它应该沿着移动的圆圈拖动,当我们的拖动组件在移动的圆圈内时,应该有一个秒表,它是 运行 并且当我们移除手或可拖动组件在移动的圆圈之外,计时器应该重置并从第一个开始。我已经创建了拖动组件和秒表,但我无法获得如何组合它们的逻辑。
import React, {Component} from 'react'
import { View, Dimensions,TouchableHighlight,Text, StyleSheet, PanResponder, Animated} from 'react-native'
import { Stopwatch } from 'react-native-stopwatch-timer'
let {width:W,height:H} = Dimensions.get("window");
class Draggable extends Component {
constructor(props) {
super(props);
this.state = {
showDraggable: true,
pan: new Animated.ValueXY(),
opacity: new Animated.Value(1)
};
}
componentWillMount() {
this._val = { x:0, y:0 }
this.state.pan.addListener((value) => this._val = value);
this.panResponder = PanResponder.create({
onStartShouldSetPanResponder: (e, gesture) => true,
onPanResponderGrant: (e, gesture) => {
this.state.pan.setOffset({
x: this._val.x,
y:this._val.y
})
//console.log(this.state.pan);
this.state.pan.setValue({ x:0, y:0})
},
onPanResponderMove: Animated.event([
null, { dx: this.state.pan.x, dy: this.state.pan.y }
]),
onPanResponderRelease: (e, gesture) => {
this.state.pan.setOffset({x: this._val.x, y: this._val.y});
}
});
}
render() {
return (
<View>
{this.renderDraggable()}
</View>
);
}
renderDraggable() {
const panStyle = {
transform: this.state.pan.getTranslateTransform()
}
if (this.state.showDraggable) {
return (
<Animated.View
{...this.panResponder.panHandlers}
style={[panStyle, styles.circle, styles.dragstyle,{opacity:this.state.opacity}]}
/>
);
}
}
}
class MovingCircle extends React.Component{
constructor(props){
super(props);
this.state={
pos:new Animated.ValueXY
}
}
_loopAnimation(){
let des = {x:W*Math.random(), y:Math.random()*H};
//console.log(this.state.des)
Animated.timing(this.state.pos, {
toValue:des,
duration:4000
}).start(()=>{
this._loopAnimation();
});
}
componentDidMount(){
this._loopAnimation();
}
render(){
return <Animated.View style={{
width:60,height:60,
borderRadius:30,
backgroundColor:"#0A8648",
position:"absolute",
left:this.state.pos.x,
top:this.state.pos.y
}}/>
}
}
export default class App extends React.Component {
constructor (props) {
super(props);
this.state = {
stopwatchStart: false,
stopwatchReset: false,
};
this.toggleStopwatch = this.toggleStopwatch.bind(this);
this.resetStopwatch = this.resetStopwatch.bind(this);
}
toggleStopwatch() {
this.setState({stopwatchStart: !this.state.stopwatchStart, stopwatchReset: false});
}
resetStopwatch() {
this.setState({stopwatchStart: false, stopwatchReset: true});
}
getFormattedTime(time) {
this.currentTime = time;
}
render() {
return (
<View style={styles.mainContainer} >
<MovingCircle />
<View style={styles.dragContainer}>
<Draggable />
</View>
<View style={styles.stopWatchHeader} >
<Stopwatch laps msecs start={this.state.stopwatchStart}
reset={this.state.stopwatchReset}
getTime={this.getFormattedTime} />
<View style={styles.startResetHeader} >
<TouchableHighlight onPress={this.toggleStopwatch}>
<Text style={{fontSize: 20}}>{!this.state.stopwatchStart ? "Start" : "Stop"}</Text>
</TouchableHighlight>
<TouchableHighlight onPress={this.resetStopwatch}>
<Text style={{fontSize: 20}}>Reset</Text>
</TouchableHighlight>
</View>
</View>
</View>
);
}
}
let CIRCLE_RADIUS = 25;
const styles = StyleSheet.create({
mainContainer: {
flex: 1,
backgroundColor:"#D7B68A"
},
circle: {
backgroundColor: "#38395E",
width: CIRCLE_RADIUS * 2,
height: CIRCLE_RADIUS * 2,
borderRadius: CIRCLE_RADIUS
},
dragContainer: {
flex: 1,
flexDirection: "row",
height:150,
justifyContent: "flex-start",
alignItems: "flex-end"
},
stopWatchHeader:{
flexDirection:"row",
backgroundColor:"#FFDEAD",
alignItems:"center",
justifyContent:"space-between",
height:66,
padding:8,
borderRadius:4
},
startResetHeader:{
flex:1,
flexDirection:"row",
justifyContent:"space-around"
}
})
下面是示例,动画持续时间和视图大小自行调整。看看 official document of Animations
import React, {Component} from 'react'
import { View,
Dimensions,
StyleSheet, Animated} from 'react-native'
let {width:W,height:H} = Dimensions.get("window");
export default class test0123 extends React.Component{
constructor(props){
super(props);
this.state={
pos:new Animated.ValueXY
}
}
_loopAnimation(){
let des = {x:W*Math.random(), y:Math.random()*H};
Animated.timing(this.state.pos, {
toValue:des,
duration:3000
}).start(()=>{
this._loopAnimation();
});
}
componentDidMount(){
this._loopAnimation();
}
render(){
return <Animated.View style={{
width:50,height:50,
borderRadius:25,
backgroundColor:"red",
position:"absolute",
left:this.state.pos.x,
top:this.state.pos.y
}}/>
}
}
您需要在声明的状态中调用 new Animated.ValueXY()
。
我是 React Native 的新手。我正在尝试构建一个需要在屏幕上随机移动的视图(圆圈)的功能。有人可以帮我从哪里开始吗?提前致谢。
更新:我现在正在尝试创建一个可拖动的组件,它应该沿着移动的圆圈拖动,当我们的拖动组件在移动的圆圈内时,应该有一个秒表,它是 运行 并且当我们移除手或可拖动组件在移动的圆圈之外,计时器应该重置并从第一个开始。我已经创建了拖动组件和秒表,但我无法获得如何组合它们的逻辑。
import React, {Component} from 'react'
import { View, Dimensions,TouchableHighlight,Text, StyleSheet, PanResponder, Animated} from 'react-native'
import { Stopwatch } from 'react-native-stopwatch-timer'
let {width:W,height:H} = Dimensions.get("window");
class Draggable extends Component {
constructor(props) {
super(props);
this.state = {
showDraggable: true,
pan: new Animated.ValueXY(),
opacity: new Animated.Value(1)
};
}
componentWillMount() {
this._val = { x:0, y:0 }
this.state.pan.addListener((value) => this._val = value);
this.panResponder = PanResponder.create({
onStartShouldSetPanResponder: (e, gesture) => true,
onPanResponderGrant: (e, gesture) => {
this.state.pan.setOffset({
x: this._val.x,
y:this._val.y
})
//console.log(this.state.pan);
this.state.pan.setValue({ x:0, y:0})
},
onPanResponderMove: Animated.event([
null, { dx: this.state.pan.x, dy: this.state.pan.y }
]),
onPanResponderRelease: (e, gesture) => {
this.state.pan.setOffset({x: this._val.x, y: this._val.y});
}
});
}
render() {
return (
<View>
{this.renderDraggable()}
</View>
);
}
renderDraggable() {
const panStyle = {
transform: this.state.pan.getTranslateTransform()
}
if (this.state.showDraggable) {
return (
<Animated.View
{...this.panResponder.panHandlers}
style={[panStyle, styles.circle, styles.dragstyle,{opacity:this.state.opacity}]}
/>
);
}
}
}
class MovingCircle extends React.Component{
constructor(props){
super(props);
this.state={
pos:new Animated.ValueXY
}
}
_loopAnimation(){
let des = {x:W*Math.random(), y:Math.random()*H};
//console.log(this.state.des)
Animated.timing(this.state.pos, {
toValue:des,
duration:4000
}).start(()=>{
this._loopAnimation();
});
}
componentDidMount(){
this._loopAnimation();
}
render(){
return <Animated.View style={{
width:60,height:60,
borderRadius:30,
backgroundColor:"#0A8648",
position:"absolute",
left:this.state.pos.x,
top:this.state.pos.y
}}/>
}
}
export default class App extends React.Component {
constructor (props) {
super(props);
this.state = {
stopwatchStart: false,
stopwatchReset: false,
};
this.toggleStopwatch = this.toggleStopwatch.bind(this);
this.resetStopwatch = this.resetStopwatch.bind(this);
}
toggleStopwatch() {
this.setState({stopwatchStart: !this.state.stopwatchStart, stopwatchReset: false});
}
resetStopwatch() {
this.setState({stopwatchStart: false, stopwatchReset: true});
}
getFormattedTime(time) {
this.currentTime = time;
}
render() {
return (
<View style={styles.mainContainer} >
<MovingCircle />
<View style={styles.dragContainer}>
<Draggable />
</View>
<View style={styles.stopWatchHeader} >
<Stopwatch laps msecs start={this.state.stopwatchStart}
reset={this.state.stopwatchReset}
getTime={this.getFormattedTime} />
<View style={styles.startResetHeader} >
<TouchableHighlight onPress={this.toggleStopwatch}>
<Text style={{fontSize: 20}}>{!this.state.stopwatchStart ? "Start" : "Stop"}</Text>
</TouchableHighlight>
<TouchableHighlight onPress={this.resetStopwatch}>
<Text style={{fontSize: 20}}>Reset</Text>
</TouchableHighlight>
</View>
</View>
</View>
);
}
}
let CIRCLE_RADIUS = 25;
const styles = StyleSheet.create({
mainContainer: {
flex: 1,
backgroundColor:"#D7B68A"
},
circle: {
backgroundColor: "#38395E",
width: CIRCLE_RADIUS * 2,
height: CIRCLE_RADIUS * 2,
borderRadius: CIRCLE_RADIUS
},
dragContainer: {
flex: 1,
flexDirection: "row",
height:150,
justifyContent: "flex-start",
alignItems: "flex-end"
},
stopWatchHeader:{
flexDirection:"row",
backgroundColor:"#FFDEAD",
alignItems:"center",
justifyContent:"space-between",
height:66,
padding:8,
borderRadius:4
},
startResetHeader:{
flex:1,
flexDirection:"row",
justifyContent:"space-around"
}
})
下面是示例,动画持续时间和视图大小自行调整。看看 official document of Animations
import React, {Component} from 'react'
import { View,
Dimensions,
StyleSheet, Animated} from 'react-native'
let {width:W,height:H} = Dimensions.get("window");
export default class test0123 extends React.Component{
constructor(props){
super(props);
this.state={
pos:new Animated.ValueXY
}
}
_loopAnimation(){
let des = {x:W*Math.random(), y:Math.random()*H};
Animated.timing(this.state.pos, {
toValue:des,
duration:3000
}).start(()=>{
this._loopAnimation();
});
}
componentDidMount(){
this._loopAnimation();
}
render(){
return <Animated.View style={{
width:50,height:50,
borderRadius:25,
backgroundColor:"red",
position:"absolute",
left:this.state.pos.x,
top:this.state.pos.y
}}/>
}
}
您需要在声明的状态中调用 new Animated.ValueXY()
。