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 ScaleSlider from './scaleSlider/scaleSliderView';
|
||||||
import UserListItem from './basicUIElements/view/userListItem/userListItem';
|
import UserListItem from './basicUIElements/view/userListItem/userListItem';
|
||||||
import PostButton from './postButton/postButtonView';
|
import PostButton from './postButton/postButtonView';
|
||||||
|
import SpinGame from './spinGame/view/spinGameView';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
CircularButton,
|
CircularButton,
|
||||||
@ -17,6 +18,7 @@ export {
|
|||||||
Icon,
|
Icon,
|
||||||
IconButton,
|
IconButton,
|
||||||
Logo,
|
Logo,
|
||||||
|
SpinGame,
|
||||||
Modal,
|
Modal,
|
||||||
NumericKeyboard,
|
NumericKeyboard,
|
||||||
PinAnimatedInput,
|
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 { injectIntl } from 'react-intl';
|
||||||
import { View, Text } from 'react-native';
|
import { View, Text } from 'react-native';
|
||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
|
import wheel from './wheel.png';
|
||||||
|
import marker from './marker.png';
|
||||||
// Container
|
// Container
|
||||||
import { PointsContainer } from '../../../containers';
|
import { PointsContainer } from '../../../containers';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import { BasicHeader } from '../../../components/basicHeader';
|
import { BasicHeader } from '../../../components/basicHeader';
|
||||||
|
import { SpinGame } from '../../../components';
|
||||||
|
|
||||||
// Styles
|
// Styles
|
||||||
import styles from './freeEstmStyles';
|
import styles from './freeEstmStyles';
|
||||||
@ -20,19 +22,98 @@ class FreeEstmScreen extends PureComponent {
|
|||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(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() {
|
render() {
|
||||||
const { intl } = this.props;
|
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 (
|
return (
|
||||||
<PointsContainer>
|
<PointsContainer>
|
||||||
{({ isLoading, balance: _balance }) => (
|
{({ isLoading, balance: _balance }) => (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<BasicHeader title={intl.formatMessage({ id: 'free_estm.title' })} />
|
<BasicHeader title={intl.formatMessage({ id: 'free_estm.title' })} />
|
||||||
<View style={styles.container}>
|
<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>
|
</View>
|
||||||
</Fragment>
|
</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