mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-08-15 18:45:06 +00:00
174 lines
4.0 KiB
JavaScript
174 lines
4.0 KiB
JavaScript
/**
|
|
* @flow
|
|
*/
|
|
import React from 'react';
|
|
import { PanResponder, StyleSheet, View } from 'react-native';
|
|
import Example from '../../shared/example';
|
|
|
|
const CIRCLE_SIZE = 80;
|
|
|
|
class DraggableCircle extends React.PureComponent {
|
|
_panResponder = {};
|
|
_previousLeft = 0;
|
|
_previousTop = 0;
|
|
_circleStyles = {};
|
|
circle = null;
|
|
|
|
constructor() {
|
|
super();
|
|
this._panResponder = PanResponder.create({
|
|
onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder,
|
|
onMoveShouldSetPanResponder: this._handleMoveShouldSetPanResponder,
|
|
onPanResponderGrant: this._handlePanResponderGrant,
|
|
onPanResponderMove: this._handlePanResponderMove,
|
|
onPanResponderRelease: this._handlePanResponderEnd,
|
|
onPanResponderTerminate: this._handlePanResponderEnd
|
|
});
|
|
this._previousLeft = 20;
|
|
this._previousTop = 84;
|
|
this._circleStyles = {
|
|
left: this._previousLeft,
|
|
top: this._previousTop,
|
|
backgroundColor: 'green'
|
|
};
|
|
}
|
|
|
|
componentDidMount() {
|
|
this._updateNativeStyles();
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<View style={styles.container}>
|
|
<View
|
|
ref={this._setCircleRef}
|
|
style={[styles.circle, this._circleStyles]}
|
|
{...this._panResponder.panHandlers}
|
|
/>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
_setCircleRef = (circle) => {
|
|
this.circle = circle;
|
|
};
|
|
|
|
_highlight() {
|
|
this._circleStyles.backgroundColor = 'blue';
|
|
this._updateNativeStyles();
|
|
}
|
|
|
|
_unHighlight() {
|
|
this._circleStyles.backgroundColor = 'green';
|
|
this._updateNativeStyles();
|
|
}
|
|
|
|
_updateNativeStyles() {
|
|
this.forceUpdate();
|
|
}
|
|
|
|
_handleStartShouldSetPanResponder = (
|
|
e: Object,
|
|
gestureState: Object
|
|
): boolean => {
|
|
// Should we become active when the user presses down on the circle?
|
|
return true;
|
|
};
|
|
|
|
_handleMoveShouldSetPanResponder = (
|
|
e: Object,
|
|
gestureState: Object
|
|
): boolean => {
|
|
// Should we become active when the user moves a touch over the circle?
|
|
return true;
|
|
};
|
|
|
|
_handlePanResponderGrant = (e: Object, gestureState: Object) => {
|
|
this._highlight();
|
|
};
|
|
|
|
_handlePanResponderMove = (e: Object, gestureState: Object) => {
|
|
this._circleStyles.left = this._previousLeft + gestureState.dx;
|
|
this._circleStyles.top = this._previousTop + gestureState.dy;
|
|
this._updateNativeStyles();
|
|
};
|
|
|
|
_handlePanResponderEnd = (e: Object, gestureState: Object) => {
|
|
this._unHighlight();
|
|
this._previousLeft += gestureState.dx;
|
|
this._previousTop += gestureState.dy;
|
|
};
|
|
}
|
|
|
|
class LocationXY extends React.Component {
|
|
constructor() {
|
|
super();
|
|
this.state = { translateX: 0 };
|
|
this.panResponder = PanResponder.create({
|
|
onStartShouldSetPanResponder: () => true,
|
|
onStartShouldSetPanResponderCapture: () => true,
|
|
onPanResponderMove: this._handlePanResponderMove,
|
|
onPanResponderTerminationRequest: () => true
|
|
});
|
|
}
|
|
|
|
_handlePanResponderMove = (e, gestureState) => {
|
|
console.log(e.nativeEvent.locationX, e.nativeEvent.locationY);
|
|
this.setState((state) => ({
|
|
...state,
|
|
translateX: gestureState.dx
|
|
}));
|
|
};
|
|
|
|
render() {
|
|
const transform = { transform: `translateX(${this.state.translateX}px)` };
|
|
return (
|
|
<View style={styles.box}>
|
|
<View style={styles.outer} {...this.panResponder.panHandlers}>
|
|
<View style={[styles.inner, transform]} />
|
|
</View>
|
|
</View>
|
|
);
|
|
}
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
circle: {
|
|
width: CIRCLE_SIZE,
|
|
height: CIRCLE_SIZE,
|
|
borderRadius: CIRCLE_SIZE / 2,
|
|
position: 'absolute',
|
|
left: 0,
|
|
top: 0,
|
|
touchAction: 'none'
|
|
},
|
|
container: {
|
|
alignSelf: 'stretch',
|
|
minHeight: 300,
|
|
paddingTop: 64
|
|
},
|
|
box: {
|
|
justifyContent: 'center',
|
|
alignItems: 'center'
|
|
},
|
|
outer: {
|
|
width: 250,
|
|
height: 50,
|
|
backgroundColor: 'skyblue'
|
|
},
|
|
inner: {
|
|
width: 30,
|
|
height: 30,
|
|
backgroundColor: 'lightblue'
|
|
}
|
|
});
|
|
|
|
export default function PanResponderPage() {
|
|
return (
|
|
<Example title="PanResponder">
|
|
<DraggableCircle />
|
|
<LocationXY />
|
|
</Example>
|
|
);
|
|
}
|