-
Notifications
You must be signed in to change notification settings - Fork 14
/
Roulette.js
117 lines (99 loc) · 3.29 KB
/
Roulette.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import React, { Component, Children } from 'react';
import PropTypes from 'prop-types';
import { View, Animated, PanResponder, Easing } from 'react-native';
import RouletteItem from './RouletteItem';
import styles from './styles';
class Roulette extends Component {
constructor(props) {
super(props);
this.state = {
_animatedValue: new Animated.Value(0),
activeItem: 0
};
this.step = props.step || (2 * Math.PI) / props.children.length;
this.panResponder = PanResponder.create({
onMoveShouldSetResponderCapture: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderRelease: () => {
const { enableUserRotate, handlerOfRotate } = this.props;
if (enableUserRotate) {
const { children } = this.props;
const { activeItem } = this.state;
const nextItem = activeItem + 1;
this.state._animatedValue.setValue(activeItem);
Animated.timing(this.state._animatedValue, { toValue: nextItem, easing: Easing.linear }).start();
const newActiveItem = nextItem > children.length ? 1 : nextItem;
this.setState({ activeItem: newActiveItem }, () => handlerOfRotate(children[children.length - newActiveItem].props));
}
}
});
}
getCenterCoordinates({ x, y, width, height }) {
this.setState({ centerX: x + (width / 2), centerY: y + (height / 2) });
}
renderDefaultCenter() {
const { radius, customCenterStyle } = this.props;
return (
<View
style={[
styles.center,
{ width: radius / 10, height: radius / 10, borderRadius: radius },
customCenterStyle
]}
onLayout={(event) => this.getCenterCoordinates(event.nativeEvent.layout)}
/>
);
}
render() {
const { children, radius, distance, renderCenter, customStyle, rouletteRotate } = this.props;
const interpolatedRotateAnimation = this.state._animatedValue.interpolate({
inputRange: [0, children.length],
outputRange: [`${rouletteRotate}deg`, `${360 + rouletteRotate}deg`]
});
return (
<Animated.View
{...this.panResponder.panHandlers}
style={[
styles.container,
{ width: radius, height: radius, borderRadius: radius / 2 },
{ transform: [{ rotate: interpolatedRotateAnimation }] },
customStyle
]}
>
{
Children.map(children, (child, index) =>
<RouletteItem
item={child}
index={index}
radius={radius}
step={this.step}
distance={distance}
rouletteRotate={rouletteRotate}
/>
)}
{renderCenter() || this.renderDefaultCenter()}
</Animated.View>
);
}
}
Roulette.propTypes = {
step: PropTypes.number,
radius: PropTypes.number,
distance: PropTypes.number,
rouletteRotate: PropTypes.number,
enableUserRotate: PropTypes.bool,
children: PropTypes.any,
renderCenter: PropTypes.func,
handlerOfRotate: PropTypes.func,
customStyle: PropTypes.any,
customCenterStyle: PropTypes.any
};
Roulette.defaultProps = {
radius: 300,
distance: 100,
rouletteRotate: 0,
enableUserRotate: false,
renderCenter: () => {},
handlerOfRotate: () => {}
};
export default Roulette;