Last active
January 10, 2018 23:56
-
-
Save gaishimo/931c48e00bfe62e1408e380ed9ce8f11 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @flow | |
import React, { Component } from 'react'; | |
import { | |
StyleSheet, | |
View, | |
PanResponder, | |
} from 'react-native'; | |
type State = { | |
dragging: boolean, | |
x: number, | |
y: number, | |
draggingX: number, | |
draggingY: number, | |
} | |
type GestureState = { | |
dx: number, | |
dy: number, | |
} | |
export default class App extends Component<{}, State> { | |
state: State = { | |
dragging: false, | |
x: 100, | |
y: 100, | |
draggingX: 100, | |
draggingY: 100, | |
} | |
panResponder: any | |
componentWillMount() { | |
this.createPanResponder() | |
} | |
createPanResponder() { | |
this.panResponder = PanResponder.create({ | |
onStartShouldSetPanResponder: this.onStartShouldSetPanResponder, | |
onStartShouldSetPanResponderCapture: this.onStartShouldSetPanResponderCapture, | |
onMoveShouldSetPanResponder: this.onMoveShouldSetPanResponder, | |
onMoveShouldSetPanResponderCapture: this.onMoveShouldSetPanResponderCapture, | |
onPanResponderGrant: this.onPanResponderGrant, | |
onPanResponderMove: this.onPanResponderMove, | |
onPanResponderTerminationRequest: this.onPanResponderTerminationRequest, | |
onPanResponderRelease: this.onPanResponderEnd, | |
onPanResponderTerminate: this.onPanResponderEnd, | |
onShouldBlockNativeResponder: (evt, gestureState) => { | |
return true; | |
}, | |
}) | |
} | |
onStartShouldSetPanResponder (e: Object, gestureState: GestureState) { | |
return true | |
} | |
onMoveShouldSetPanResponder (e: Object, gestureState: GestureState) { | |
return true | |
} | |
onMoveShouldSetPanResponderCapture (e: Object, gestureState: GestureState) { | |
return true | |
} | |
onPanResponderGrant = (e: Object, gestureState: GestureState) => { | |
this.setState({ dragging: true }) | |
} | |
onStartShouldSetPanResponderCapture = (e: Object, gestureState: GestureState) => { | |
return true | |
} | |
onPanResponderMove = (e: Object, gestureState: GestureState) => { | |
const { x, y } = this.state | |
const { dx, dy } = gestureState | |
this.setState({ | |
draggingX: x + dx, | |
draggingY: y + dy, | |
}) | |
} | |
onPanResponderEnd = (e: Object, gestureState: GestureState) => { | |
this.setState({ | |
x: this.state.draggingX, | |
y: this.state.draggingY, | |
dragging: false, | |
}) | |
} | |
onPanResponderTerminationRequest(e: Object, gestureState: GestureState) { | |
return true | |
} | |
render() { | |
const { x, y, dragging, draggingX, draggingY } = this.state | |
const backgroundColor = dragging ? '#FFEF15' : 'rgb(200, 240, 250)' | |
const left = dragging ? draggingX : x | |
const top = dragging ? draggingY : y | |
return ( | |
<View | |
style={[ | |
styles.responder, | |
{ | |
backgroundColor, | |
left, | |
top, | |
} | |
]} | |
{...this.panResponder.panHandlers} | |
/> | |
); | |
} | |
} | |
const styles = StyleSheet.create({ | |
container: { | |
flex: 1, | |
justifyContent: 'center', | |
alignItems: 'center', | |
}, | |
responder: { | |
position: 'absolute', | |
width: 100, | |
height: 100, | |
borderRadius: 10, | |
}, | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @flow | |
import React, { Component } from 'react'; | |
import { | |
StyleSheet, | |
View, | |
PanResponder, | |
Text, | |
} from 'react-native'; | |
type State = { | |
dragging: boolean, | |
radius: number, | |
moveX: ?number, | |
moveY: ?number, | |
} | |
type GestureState = Object | |
const centerX = 180 | |
const centerY = 300 | |
const minRadius = 30 | |
const maxRadius = 120 | |
export default class App extends Component<{}, State> { | |
state: State = { | |
dragging: false, | |
radius: 30, | |
moveX: null, | |
moveY: null, | |
} | |
panResponder: any | |
componentWillMount() { | |
this.createPanResponder() | |
} | |
createPanResponder() { | |
this.panResponder = PanResponder.create({ | |
onStartShouldSetPanResponder: this.onStartShouldSetPanResponder, | |
onStartShouldSetPanResponderCapture: this.onStartShouldSetPanResponderCapture, | |
onMoveShouldSetPanResponder: this.onMoveShouldSetPanResponder, | |
onMoveShouldSetPanResponderCapture: this.onMoveShouldSetPanResponderCapture, | |
onPanResponderGrant: this.onPanResponderGrant, | |
onPanResponderMove: this.onPanResponderMove, | |
onPanResponderTerminationRequest: this.onPanResponderTerminationRequest, | |
onPanResponderRelease: this.onPanResponderEnd, | |
onPanResponderTerminate: this.onPanResponderEnd, | |
onShouldBlockNativeResponder: this.onShouldBlockNativeResponder, | |
}) | |
} | |
onStartShouldSetPanResponder (e: Object, gestureState: GestureState) { | |
return true | |
} | |
onMoveShouldSetPanResponder (e: Object, gestureState: GestureState) { | |
return true | |
} | |
onMoveShouldSetPanResponderCapture (e: Object, gestureState: GestureState) { | |
return true | |
} | |
onPanResponderGrant = (e: Object, gestureState: GestureState) => { | |
this.setState({ dragging: true }) | |
} | |
onStartShouldSetPanResponderCapture = (e: Object, gestureState: GestureState) => { | |
return true | |
} | |
onPanResponderMove = (e: Object, gestureState: GestureState) => { | |
const { moveX, moveY, x0, y0, dx, dy, vx, vy } = gestureState | |
const previousMoveX = this.state.moveX | |
const previousMoveY = this.state.moveY | |
if (previousMoveX == null || previousMoveY == null) { | |
this.setState({ moveX, moveY }) | |
return | |
} | |
const xFromCenter = Math.abs(centerX - moveX) | |
const yFromCenter = Math.abs(centerY - moveY) | |
const previousXFromCenter = Math.abs(centerX - previousMoveX) | |
const previousYFromCenter = Math.abs(centerY - previousMoveY) | |
const useHorizontalChange = Math.abs(xFromCenter) > Math.abs(yFromCenter) | |
const expanding = useHorizontalChange ? | |
xFromCenter > previousXFromCenter | |
: yFromCenter > previousYFromCenter | |
let radius = useHorizontalChange ? xFromCenter : yFromCenter | |
radius = Math.round(radius / 10) * 10 | |
if (expanding) { | |
if (this.state.radius > radius || radius > maxRadius) { | |
// 大きくしようとしているが元より小さい場合 | |
this.setState({ moveX, moveY }) | |
return | |
} | |
} else { | |
if (this.state.radius < radius || radius < minRadius) { | |
// 小さくしようとしているが元より大きい場合 | |
this.setState({ moveX, moveY }) | |
return | |
} | |
} | |
this.setState({ radius }) | |
} | |
onPanResponderEnd = (e: Object, gestureState: GestureState) => { | |
this.setState({ | |
dragging: false, | |
moveX: null, | |
moveY: null, | |
}) | |
} | |
onPanResponderTerminationRequest(e: Object, gestureState: GestureState) { | |
return true | |
} | |
onShouldBlockNativeResponder(e: Object, gestureState: GestureState) { | |
return true | |
} | |
render() { | |
const { dragging, radius } = this.state | |
const backgroundColor = dragging ? '#CCE8E8' : '#B0D3E1' | |
const width = radius * 2 | |
const height = radius * 2 | |
const left = centerX - radius | |
const top = centerY - radius | |
const num = radius / 10 - 2 | |
// console.log(left, top, width, height) | |
return ( | |
<View | |
style={[ | |
styles.responder, | |
{ | |
left, | |
top, | |
width, | |
height, | |
backgroundColor, | |
borderRadius: radius, | |
} | |
]} | |
{...this.panResponder.panHandlers} | |
> | |
<Text style={styles.num}>{num}</Text> | |
</View> | |
); | |
} | |
} | |
const styles = StyleSheet.create({ | |
container: { | |
flex: 1, | |
justifyContent: 'center', | |
alignItems: 'center', | |
}, | |
responder: { | |
position: 'absolute', | |
justifyContent: 'center', | |
alignItems: 'center', | |
}, | |
num: { | |
color: 'white', | |
fontSize: 28, | |
fontWeight: 'bold', | |
}, | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment