mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-18 02:41:39 +03:00
start to work with spin game
This commit is contained in:
parent
32555b803b
commit
323d688a47
Binary file not shown.
@ -10,6 +10,7 @@ import { TextInput } from './textInput';
|
||||
import ScaleSlider from './scaleSlider/scaleSliderView';
|
||||
import UserListItem from './basicUIElements/view/userListItem/userListItem';
|
||||
import PostButton from './postButton/postButtonView';
|
||||
import SpinGame from './spinGame/view/spinGameView';
|
||||
|
||||
export {
|
||||
CircularButton,
|
||||
@ -17,6 +18,7 @@ export {
|
||||
Icon,
|
||||
IconButton,
|
||||
Logo,
|
||||
SpinGame,
|
||||
Modal,
|
||||
NumericKeyboard,
|
||||
PinAnimatedInput,
|
||||
|
56
src/components/spinGame/view/rouletteItem.js
Normal file
56
src/components/spinGame/view/rouletteItem.js
Normal file
@ -0,0 +1,56 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View } from 'react-native';
|
||||
|
||||
class RouletteItem extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
coordX: props.radius,
|
||||
coordY: props.radius,
|
||||
};
|
||||
}
|
||||
|
||||
getCoordinates({ width, height }) {
|
||||
const { radius, index, step, distance } = this.props;
|
||||
|
||||
const coordX = Math.round(
|
||||
radius / 2 + distance * -Math.sin(index * step - Math.PI) - width / 2,
|
||||
);
|
||||
const coordY = Math.round(
|
||||
radius / 2 + distance * Math.cos(index * step - Math.PI) - height / 2,
|
||||
);
|
||||
|
||||
this.setState({ coordX, coordY });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { item, rouletteRotate } = this.props;
|
||||
const { coordX, coordY } = this.state;
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
position: 'absolute',
|
||||
left: coordX,
|
||||
top: coordY,
|
||||
transform: [{ rotate: `${-rouletteRotate}deg` }],
|
||||
}}
|
||||
onLayout={event => this.getCoordinates(event.nativeEvent.layout)}
|
||||
>
|
||||
{item}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
RouletteItem.propTypes = {
|
||||
step: PropTypes.number,
|
||||
index: PropTypes.number,
|
||||
radius: PropTypes.number,
|
||||
distance: PropTypes.number,
|
||||
rouletteRotate: PropTypes.number,
|
||||
item: PropTypes.element.isRequired,
|
||||
};
|
||||
|
||||
export default RouletteItem;
|
@ -1 +1,169 @@
|
||||
//
|
||||
import React, { Component, Children } from 'react';
|
||||
import { View, Animated, PanResponder, Easing, ImageBackground, Image } 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.options.length;
|
||||
|
||||
this.panResponder = PanResponder.create({
|
||||
onMoveShouldSetResponderCapture: () => true,
|
||||
onMoveShouldSetPanResponderCapture: () => true,
|
||||
onPanResponderRelease: () => {
|
||||
const { enableUserRotate } = this.props;
|
||||
|
||||
if (enableUserRotate) this.triggerSpin();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
triggerSpin(spinToIndex) {
|
||||
const { options, turns, onRotate, onRotateChange, duration, easing } = this.props;
|
||||
const { activeItem } = this.state;
|
||||
const randomSelected = Math.floor(Math.random() * options.length);
|
||||
const selectedIndex = spinToIndex != null ? spinToIndex : randomSelected;
|
||||
const turnsMultiplier = options.length * turns;
|
||||
const nextItem = selectedIndex + turnsMultiplier;
|
||||
|
||||
this.state._animatedValue.setValue(activeItem);
|
||||
const animation = Animated.timing(this.state._animatedValue, {
|
||||
toValue: nextItem,
|
||||
easing,
|
||||
duration,
|
||||
});
|
||||
if (onRotateChange) onRotateChange('start');
|
||||
animation.start(() => {
|
||||
if (onRotateChange) onRotateChange('stop');
|
||||
});
|
||||
|
||||
let newActiveItem = nextItem > options.length ? nextItem % options.length : nextItem;
|
||||
if (newActiveItem == 0) {
|
||||
newActiveItem = options.length;
|
||||
}
|
||||
this.setState(
|
||||
{ activeItem: newActiveItem },
|
||||
() => onRotate && onRotate(options[options.length - newActiveItem]),
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
options,
|
||||
radius,
|
||||
distance,
|
||||
customStyle,
|
||||
rouletteRotate,
|
||||
background,
|
||||
marker,
|
||||
centerImage,
|
||||
markerWidth,
|
||||
markerTop,
|
||||
centerWidth,
|
||||
centerTop,
|
||||
markerStyle,
|
||||
centerStyle,
|
||||
rotateEachElement,
|
||||
} = this.props;
|
||||
|
||||
const interpolatedRotateAnimation = this.state._animatedValue.interpolate({
|
||||
inputRange: [0, options.length],
|
||||
outputRange: [`${rouletteRotate}deg`, `${360 + rouletteRotate}deg`],
|
||||
});
|
||||
|
||||
const displayOptions =
|
||||
options && options.length > 0 && options[0] && React.isValidElement(options[0]);
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Animated.View
|
||||
{...this.panResponder.panHandlers}
|
||||
style={[
|
||||
styles.container,
|
||||
{ width: radius, height: radius, borderRadius: radius / 2 },
|
||||
{ transform: [{ rotate: interpolatedRotateAnimation }] },
|
||||
customStyle,
|
||||
]}
|
||||
>
|
||||
<ImageBackground
|
||||
width={radius}
|
||||
height={radius}
|
||||
style={{ width: radius, height: radius, zIndex: 100 }}
|
||||
source={background}
|
||||
>
|
||||
{displayOptions &&
|
||||
Children.map(options, (child, index) => (
|
||||
<RouletteItem
|
||||
item={child}
|
||||
index={index}
|
||||
radius={radius}
|
||||
step={this.step}
|
||||
distance={distance}
|
||||
rouletteRotate={rotateEachElement(index)}
|
||||
/>
|
||||
))}
|
||||
</ImageBackground>
|
||||
</Animated.View>
|
||||
<Image
|
||||
source={marker}
|
||||
resizeMode="contain"
|
||||
style={[
|
||||
styles.marker,
|
||||
{
|
||||
zIndex: 9999,
|
||||
top: markerTop,
|
||||
width: markerWidth,
|
||||
left: radius / 2 - markerWidth / 2,
|
||||
},
|
||||
markerStyle,
|
||||
]}
|
||||
/>
|
||||
|
||||
{centerImage && (
|
||||
<Image
|
||||
source={centerImage}
|
||||
resizeMode="contain"
|
||||
style={[
|
||||
styles.marker,
|
||||
{
|
||||
zIndex: 9999,
|
||||
top: centerTop,
|
||||
width: centerWidth,
|
||||
left: radius / 2 - centerWidth / 2,
|
||||
},
|
||||
centerStyle,
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Roulette.defaultProps = {
|
||||
radius: 300,
|
||||
distance: 100,
|
||||
rouletteRotate: 0,
|
||||
enableUserRotate: false,
|
||||
background: null,
|
||||
turns: 5,
|
||||
rotateEachElement: index => 0,
|
||||
// onRotate: () => {},
|
||||
// onRotateChange: () => {},
|
||||
duration: 3500,
|
||||
easing: Easing.inOut(Easing.ease),
|
||||
markerTop: 0,
|
||||
markerWidth: 20,
|
||||
centerWidth: 20,
|
||||
centerTop: 0,
|
||||
centerImage: null,
|
||||
markerStyle: {},
|
||||
};
|
||||
|
||||
export default Roulette;
|
||||
|
13
src/components/spinGame/view/styles.js
Normal file
13
src/components/spinGame/view/styles.js
Normal file
@ -0,0 +1,13 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
marker: {
|
||||
position: 'absolute',
|
||||
},
|
||||
});
|
||||
|
||||
export default styles;
|
@ -2,12 +2,14 @@ import React, { PureComponent, Fragment } from 'react';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import { View, Text } from 'react-native';
|
||||
import get from 'lodash/get';
|
||||
|
||||
import wheel from './wheel.png';
|
||||
import marker from './marker.png';
|
||||
// Container
|
||||
import { PointsContainer } from '../../../containers';
|
||||
|
||||
// Components
|
||||
import { BasicHeader } from '../../../components/basicHeader';
|
||||
import { SpinGame } from '../../../components';
|
||||
|
||||
// Styles
|
||||
import styles from './freeEstmStyles';
|
||||
@ -20,19 +22,98 @@ class FreeEstmScreen extends PureComponent {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
this.state = {
|
||||
rouletteState: '',
|
||||
option: '',
|
||||
rouletteCustomState: 'stop',
|
||||
optionCustom: '',
|
||||
};
|
||||
}
|
||||
|
||||
_onRotateChange(state) {
|
||||
this.setState({
|
||||
rouletteState: state,
|
||||
});
|
||||
}
|
||||
|
||||
_onRotate(option) {
|
||||
this.setState({
|
||||
option: option.index,
|
||||
});
|
||||
}
|
||||
|
||||
_onRotateCustomChange(state) {
|
||||
// this.setState({
|
||||
// rouletteCustomState: state,
|
||||
// });
|
||||
}
|
||||
|
||||
_onRotateCustom(option) {
|
||||
this.setState({
|
||||
optionCustom: option.props.index,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl } = this.props;
|
||||
const numbers = [
|
||||
100,
|
||||
320,
|
||||
150,
|
||||
192,
|
||||
43,
|
||||
213,
|
||||
23,
|
||||
235,
|
||||
137,
|
||||
334,
|
||||
633,
|
||||
273,
|
||||
133,
|
||||
363,
|
||||
113,
|
||||
303,
|
||||
83,
|
||||
233,
|
||||
130,
|
||||
53,
|
||||
234,
|
||||
136,
|
||||
33,
|
||||
];
|
||||
const options = numbers.map(o => ({ index: o }));
|
||||
const { rouletteCustomState, rouletteState, option, optionCustom } = this.state;
|
||||
|
||||
// const options = numbers.map(o => ({ index: o }));
|
||||
const customOptions = numbers.map(o => <Text index={o}>{o}</Text>);
|
||||
return (
|
||||
<PointsContainer>
|
||||
{({ isLoading, balance: _balance }) => (
|
||||
<Fragment>
|
||||
<BasicHeader title={intl.formatMessage({ id: 'free_estm.title' })} />
|
||||
<View style={styles.container}>
|
||||
<Text>free esteem</Text>
|
||||
<Text>{rouletteState}</Text>
|
||||
<Text>{option}</Text>
|
||||
<Text>{optionCustom}</Text>
|
||||
|
||||
<SpinGame
|
||||
enableUserRotate={rouletteCustomState === 'stop'}
|
||||
background={null}
|
||||
onRotate={_option =>
|
||||
this.setState({
|
||||
optionCustom: _option.props.index,
|
||||
})
|
||||
}
|
||||
onRotateChange={state =>
|
||||
this.setState({
|
||||
rouletteCustomState: state,
|
||||
})
|
||||
}
|
||||
marker={marker}
|
||||
options={customOptions}
|
||||
rotateEachElement={index => ((index * 360) / options.length) * -1 - 90}
|
||||
markerWidth={20}
|
||||
/>
|
||||
</View>
|
||||
</Fragment>
|
||||
)}
|
||||
|
BIN
src/screens/freeEstm/screen/marker.png
Normal file
BIN
src/screens/freeEstm/screen/marker.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
src/screens/freeEstm/screen/wheel.png
Normal file
BIN
src/screens/freeEstm/screen/wheel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 141 KiB |
Loading…
Reference in New Issue
Block a user