Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import * as React from 'react';
- import {
- View,
- StyleSheet,
- Animated,
- Dimensions,
- PanResponder,
- PanResponderInstance,
- Vibration,
- Easing
- } from 'react-native';
- import {observable,computed} from 'mobx';
- import {observer} from 'mobx-react'
- import ViewModel from './store';
- const {width,height} =Dimensions.get('window');
- var flatten = require('flattenStyle');
- interface JoystickProps
- {
- beforeResponderMove?(distance:number,angleInRadians:number):void;
- onResponderMove?(distance:number,angleInRadians:number):void;
- beforeResponderRelease?(oldX:number,oldY:number):void;
- onResponderRelease?(distance:number,angleInRadians:number):void;
- onResponderReleasing?(x:number,y:number);
- onReleaseFinished?();
- onInit?(viewModel:ViewModel):void;
- }
- interface JoystickState
- {
- pan:Animated.ValueXY,
- startAnimation:Animated.ValueXY,
- mainCircleBackground:string
- mainCircleSide:number
- mainCircleBorder:number
- }
- @observer
- export default class Joystick extends React.Component<JoystickProps,JoystickState>
- {
- private RADIUS = 120;
- private PanResponder : PanResponderInstance;
- private view : any;
- public viewModel : ViewModel;
- get ViewModel():ViewModel{return this.viewModel;}
- get Radius():number {return this.RADIUS;}
- constructor(props)
- {
- super(props);
- this.state = {
- pan: new Animated.ValueXY({x:0,y:0}),
- startAnimation:new Animated.ValueXY({x:0,y:0}),
- mainCircleBackground:'#F2F1EF',
- mainCircleSide: 1,
- mainCircleBorder: 1
- }
- this.state.startAnimation.addListener(({x,y})=>
- {
- this.setState({mainCircleBorder : Math.round((width/2) * y),mainCircleSide : Math.round((width - 40) * x)})
- });
- Animated.timing(
- this.state.startAnimation,
- {toValue:{x:1,y:1}, duration:750, easing:Easing.bounce}
- ).start();
- this.state.pan.addListener(({x,y})=>{
- const [newX,newY] = [Math.floor(x),Math.floor(y)];
- if(this.props.onResponderReleasing != null)
- this.props.onResponderReleasing(newX,newY);
- if(newX == 0 && newY == 0 && this.props.onReleaseFinished !=null)
- this.props.onReleaseFinished();
- })
- this.viewModel = new ViewModel(width,height,this.RADIUS);
- this.PanResponder = PanResponder.create({
- onStartShouldSetPanResponder : this.ViewModel.onStartShouldSetPanResponder,
- onPanResponderGrant: (evt, gestureState) => {
- Vibration.vibrate([0,250,200],false);
- },
- onPanResponderMove: (event,gestureEvent) =>
- {
- if(this.props.beforeResponderMove !=null)
- this.props.beforeResponderMove(this.ViewModel.distance,this.ViewModel.angleInRadians);
- this.ViewModel.onPanResponderMove(gestureEvent.x0,gestureEvent.y0,gestureEvent.dx,gestureEvent.dy);
- if(this.props.onResponderMove !=null)
- this.props.onResponderMove(this.ViewModel.distance,this.ViewModel.angleInRadians);
- this.state.pan.setValue({x:this.ViewModel.x,y:this.ViewModel.y});
- },
- onPanResponderRelease: (e, gesture) => {
- const [oldX,oldY,distance] = [this.viewModel.x,this.viewModel.y,this.viewModel.distance];
- if(this.props.beforeResponderRelease !=null)
- this.props.beforeResponderRelease(oldX,oldY);
- this.ViewModel.onPanResponderRelease();
- if(this.props.onResponderRelease !=null)
- this.props.onResponderRelease(this.ViewModel.distance,this.ViewModel.angleInRadians);
- Animated.timing(
- this.state.pan,
- {
- toValue:{x:0,y:0},
- duration:Math.round(distance/200 * 1000),
- easing:Easing.bounce
- }
- ).start();
- //
- }
- })
- this.props.onInit(this.viewModel);
- }
- render()
- {
- return(
- <View>
- <View style={{width:width, height:width, padding:20, justifyContent:'center', alignItems:'center'}}>
- <View style={{width:this.state.mainCircleSide, height:this.state.mainCircleSide,borderRadius:this.state.mainCircleBorder,backgroundColor:this.state.mainCircleBackground}}></View>
- </View>
- <View style={{ position : 'absolute', top : (width/2 - CIRCLE_RADIUS), left : (width/2 - CIRCLE_RADIUS)}}>
- <Animated.View {...this.PanResponder.panHandlers}
- ref={(view)=>this.view = view}
- style={[ styles.circle,{left:this.state.pan.x,top:this.state.pan.y},{width: CIRCLE_RADIUS*2,height: CIRCLE_RADIUS*2}]}>
- </Animated.View>
- </View>
- </View>);
- }
- }
- const CIRCLE_RADIUS = 40;
- const styles =StyleSheet.create({
- mainContainer: {
- flex : 1,
- backgroundColor:'#ABB7B7'
- },
- statusBar : {
- flex:1,
- height : 200,
- backgroundColor:'#ABB7B7',
- },
- draggableContainer: {
- position : 'absolute',
- top : (width/2 - CIRCLE_RADIUS),
- left : (width/2 - CIRCLE_RADIUS),
- },
- circle : {
- backgroundColor : '#1abc9c',
- borderRadius : CIRCLE_RADIUS,
- position:'absolute',
- top:0,
- left:0
- }
- });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement