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()