SHARE
TWEET

Untitled

a guest Oct 19th, 2017 63 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import * as React from 'react';
  2. import {
  3.     View,
  4.     StyleSheet,
  5.     Animated,
  6.     Dimensions,
  7.     PanResponder,
  8.     PanResponderInstance,
  9.     Vibration,
  10.     Easing
  11. } from 'react-native';
  12. import {observable,computed} from 'mobx';
  13. import {observer} from 'mobx-react'
  14. import ViewModel from './store';
  15. const {width,height} =Dimensions.get('window');
  16.  
  17.  
  18. var flatten = require('flattenStyle');
  19.  
  20. interface JoystickProps
  21. {
  22.     beforeResponderMove?(distance:number,angleInRadians:number):void;
  23.     onResponderMove?(distance:number,angleInRadians:number):void;
  24.     beforeResponderRelease?(oldX:number,oldY:number):void;
  25.     onResponderRelease?(distance:number,angleInRadians:number):void;
  26.     onResponderReleasing?(x:number,y:number);
  27.     onReleaseFinished?();
  28.     onInit?(viewModel:ViewModel):void;
  29. }
  30.  
  31. interface JoystickState
  32. {
  33.     pan:Animated.ValueXY,
  34.     startAnimation:Animated.ValueXY,
  35.     mainCircleBackground:string
  36.     mainCircleSide:number
  37.     mainCircleBorder:number
  38. }
  39.  
  40.  
  41. @observer  
  42. export default class Joystick extends React.Component<JoystickProps,JoystickState>
  43. {
  44.     private RADIUS = 120;
  45.     private PanResponder : PanResponderInstance;
  46.     private view : any;
  47.     public  viewModel : ViewModel;
  48.  
  49.     get ViewModel():ViewModel{return this.viewModel;}
  50.     get Radius():number {return this.RADIUS;}
  51.     constructor(props)
  52.     {
  53.         super(props);
  54.         this.state = {
  55.             pan: new Animated.ValueXY({x:0,y:0}),
  56.             startAnimation:new Animated.ValueXY({x:0,y:0}),  
  57.             mainCircleBackground:'#F2F1EF',
  58.             mainCircleSide: 1,
  59.             mainCircleBorder: 1
  60.         }
  61.         this.state.startAnimation.addListener(({x,y})=>
  62.         {
  63.             this.setState({mainCircleBorder : Math.round((width/2) * y),mainCircleSide : Math.round((width - 40) * x)})
  64.         });
  65.  
  66.         Animated.timing(
  67.             this.state.startAnimation,
  68.             {toValue:{x:1,y:1}, duration:750, easing:Easing.bounce}
  69.         ).start();
  70.  
  71.         this.state.pan.addListener(({x,y})=>{
  72.             const [newX,newY] = [Math.floor(x),Math.floor(y)];
  73.             if(this.props.onResponderReleasing != null)
  74.                 this.props.onResponderReleasing(newX,newY);
  75.             if(newX == 0 && newY == 0 && this.props.onReleaseFinished !=null)
  76.                 this.props.onReleaseFinished();
  77.         })
  78.         this.viewModel = new ViewModel(width,height,this.RADIUS);
  79.         this.PanResponder  = PanResponder.create({
  80.         onStartShouldSetPanResponder : this.ViewModel.onStartShouldSetPanResponder,
  81.          onPanResponderGrant: (evt, gestureState) => {
  82.              Vibration.vibrate([0,250,200],false);
  83.         },
  84.         onPanResponderMove: (event,gestureEvent) =>
  85.         {
  86.             if(this.props.beforeResponderMove !=null)
  87.                 this.props.beforeResponderMove(this.ViewModel.distance,this.ViewModel.angleInRadians);
  88.             this.ViewModel.onPanResponderMove(gestureEvent.x0,gestureEvent.y0,gestureEvent.dx,gestureEvent.dy);
  89.             if(this.props.onResponderMove !=null)
  90.                 this.props.onResponderMove(this.ViewModel.distance,this.ViewModel.angleInRadians);
  91.             this.state.pan.setValue({x:this.ViewModel.x,y:this.ViewModel.y});
  92.         },
  93.         onPanResponderRelease: (e, gesture) => {
  94.             const [oldX,oldY,distance] = [this.viewModel.x,this.viewModel.y,this.viewModel.distance];
  95.             if(this.props.beforeResponderRelease !=null)
  96.                 this.props.beforeResponderRelease(oldX,oldY);
  97.             this.ViewModel.onPanResponderRelease();
  98.             if(this.props.onResponderRelease !=null)
  99.                 this.props.onResponderRelease(this.ViewModel.distance,this.ViewModel.angleInRadians);
  100.  
  101.             Animated.timing(
  102.                         this.state.pan,        
  103.                         {
  104.                             toValue:{x:0,y:0},
  105.                             duration:Math.round(distance/200 * 1000),
  106.                             easing:Easing.bounce
  107.                         }    
  108.                 ).start();
  109.                 //
  110.         }  
  111.     })
  112.     this.props.onInit(this.viewModel);
  113. }
  114.  
  115.     render()
  116.     {
  117.        
  118.         return(
  119.         <View>
  120.             <View style={{width:width, height:width, padding:20, justifyContent:'center', alignItems:'center'}}>
  121.                 <View style={{width:this.state.mainCircleSide, height:this.state.mainCircleSide,borderRadius:this.state.mainCircleBorder,backgroundColor:this.state.mainCircleBackground}}></View>
  122.             </View>
  123.  
  124.             <View style={{ position : 'absolute', top : (width/2 - CIRCLE_RADIUS), left : (width/2 - CIRCLE_RADIUS)}}>
  125.                 <Animated.View {...this.PanResponder.panHandlers}                      
  126.                     ref={(view)=>this.view = view}
  127.                     style={[ styles.circle,{left:this.state.pan.x,top:this.state.pan.y},{width: CIRCLE_RADIUS*2,height: CIRCLE_RADIUS*2}]}>
  128.                 </Animated.View>
  129.             </View>
  130.         </View>);
  131.     }
  132. }
  133.  
  134.  
  135. const CIRCLE_RADIUS = 40;
  136. const styles =StyleSheet.create({
  137.     mainContainer: {
  138.         flex    : 1,
  139.         backgroundColor:'#ABB7B7'
  140.     },  
  141.     statusBar    : {
  142.         flex:1,
  143.         height         : 200,
  144.         backgroundColor:'#ABB7B7',
  145.     },
  146.     draggableContainer: {
  147.         position : 'absolute',
  148.         top : (width/2 - CIRCLE_RADIUS),
  149.         left : (width/2 - CIRCLE_RADIUS),
  150.  
  151.     },
  152.     circle      : {
  153.         backgroundColor     : '#1abc9c',
  154.         borderRadius        : CIRCLE_RADIUS,
  155.         position:'absolute',
  156.         top:0,
  157.         left:0
  158.     }
  159. });
RAW Paste Data
Top