mirror of
https://github.com/ecency/ecency-mobile.git
synced 2025-01-02 02:31:41 +03:00
created spin animation placed wip on tags
This commit is contained in:
parent
d63bd3df6e
commit
0527f2277e
@ -0,0 +1,44 @@
|
||||
import React from 'react';
|
||||
import { View, Image } from 'react-native';
|
||||
|
||||
import { SpinIndicator } from '../spinIndicator/spinIndicator';
|
||||
|
||||
// Styles
|
||||
import styles from './boostIndicatorStyles';
|
||||
|
||||
const BoostIndicatorAnimation = ({ isSpinning }) => {
|
||||
return (
|
||||
<View style={styles.spinIndicatorContainer}>
|
||||
<SpinIndicator
|
||||
size={230}
|
||||
animationDuration={2400}
|
||||
color={!isSpinning ? '#f2f2f2' : '#1a509a'}
|
||||
breadth={17}
|
||||
animating={isSpinning}
|
||||
initStart={0}
|
||||
/>
|
||||
<SpinIndicator
|
||||
size={180}
|
||||
animationDuration={2000}
|
||||
color={!isSpinning ? '#f2f2f2' : '#357ce6'}
|
||||
breadth={17}
|
||||
animating={isSpinning}
|
||||
initStart={20}
|
||||
/>
|
||||
<SpinIndicator
|
||||
size={130}
|
||||
animationDuration={1700}
|
||||
color={!isSpinning ? '#f2f2f2' : '#4da1f1'}
|
||||
breadth={17}
|
||||
animating={isSpinning}
|
||||
initStart={40}
|
||||
/>
|
||||
<Image
|
||||
style={{ width: 80, height: 80 }}
|
||||
source={require('../../../assets/esteem_logo_transparent.png')}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export { BoostIndicatorAnimation };
|
@ -0,0 +1,10 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
spinIndicatorContainer: {
|
||||
backgroundColor: '$primaryBackgroundColor',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
},
|
||||
});
|
@ -1,4 +1,5 @@
|
||||
import PulseAnimation from './pulse/pulseAnimation';
|
||||
import { PulseAnimation } from './pulse/pulseAnimation';
|
||||
import { SpinIndicator } from './spinIndicator/spinIndicator';
|
||||
import { BoostIndicatorAnimation } from './boostIndicator/boostIndicatorAnimation';
|
||||
|
||||
export { PulseAnimation };
|
||||
export default PulseAnimation;
|
||||
export { PulseAnimation, SpinIndicator, BoostIndicatorAnimation };
|
||||
|
@ -14,7 +14,7 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
export default class PulseAnimation extends Component {
|
||||
class PulseAnimation extends Component {
|
||||
static defaultProps = {
|
||||
color: 'blue',
|
||||
diameter: 400,
|
||||
@ -151,3 +151,5 @@ export default class PulseAnimation extends Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { PulseAnimation };
|
||||
|
104
src/components/animations/spinIndicator/indicator.js
Normal file
104
src/components/animations/spinIndicator/indicator.js
Normal file
@ -0,0 +1,104 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Animated, Easing } from 'react-native';
|
||||
|
||||
export default class Indicator extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
progress: new Animated.Value(0),
|
||||
};
|
||||
|
||||
this.mounted = false;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { animating } = this.props;
|
||||
|
||||
this.mounted = true;
|
||||
|
||||
if (animating) {
|
||||
this._startAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { animating } = this.props;
|
||||
|
||||
if (animating !== nextProps.animating) {
|
||||
if (animating) {
|
||||
this._stopAnimation();
|
||||
} else {
|
||||
this._startAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.mounted = false;
|
||||
}
|
||||
|
||||
_startAnimation = ({ finished } = {}) => {
|
||||
const { progress } = this.state;
|
||||
const { interaction, animationEasing, animationDuration } = this.props;
|
||||
|
||||
if (!this.mounted || finished === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
const animation = Animated.timing(progress, {
|
||||
duration: animationDuration,
|
||||
easing: animationEasing,
|
||||
useNativeDriver: true,
|
||||
isInteraction: interaction,
|
||||
toValue: 1,
|
||||
});
|
||||
|
||||
Animated.loop(animation).start();
|
||||
|
||||
this.setState({ animation });
|
||||
};
|
||||
|
||||
_stopAnimation = () => {
|
||||
const { animation } = this.state;
|
||||
|
||||
if (animation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
animation.stop();
|
||||
|
||||
this.setState({ animation: null });
|
||||
};
|
||||
|
||||
_renderComponent = (undefined, index) => {
|
||||
const { progress } = this.state;
|
||||
const { renderComponent } = this.props;
|
||||
|
||||
if (renderComponent) {
|
||||
return renderComponent({ index, progress });
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { count, ...props } = this.props;
|
||||
|
||||
return (
|
||||
<Animated.View {...props}>
|
||||
{Array.from(new Array(count), this._renderComponent)}
|
||||
</Animated.View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Indicator.defaultProps = {
|
||||
animationEasing: Easing.linear,
|
||||
animationDuration: 1200,
|
||||
animating: true,
|
||||
interaction: true,
|
||||
count: 1,
|
||||
};
|
||||
|
||||
export { Indicator };
|
126
src/components/animations/spinIndicator/spinIndicator.js
Normal file
126
src/components/animations/spinIndicator/spinIndicator.js
Normal file
@ -0,0 +1,126 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { View, Animated, Easing } from 'react-native';
|
||||
|
||||
import { Indicator } from './indicator';
|
||||
import styles from './spinIndicatorStyles';
|
||||
|
||||
class SpinIndicator extends PureComponent {
|
||||
_renderComponent = ({ index, progress }) => {
|
||||
const { size, color, animationDuration, breadth, animating, initStart } = this.props;
|
||||
|
||||
const frames = (60 * animationDuration) / 1000;
|
||||
const easing = Easing.bezier(0.4, 0.0, 0.7, 1.0);
|
||||
|
||||
const inputRange = Array.from(
|
||||
new Array(frames),
|
||||
(undefined, frameIndex) => frameIndex / (frames - 1),
|
||||
);
|
||||
|
||||
const outputRange = Array.from(new Array(frames), (undefined, frameIndex) => {
|
||||
let _progress = (2 * frameIndex) / (frames - 1);
|
||||
const rotation = index ? +(360 - 15) : -(180 - 15);
|
||||
|
||||
if (_progress > 1.0) {
|
||||
_progress = 2.0 - _progress;
|
||||
}
|
||||
|
||||
const direction = index ? -1 : +1;
|
||||
|
||||
return `${direction * (180 - 30) * easing(_progress) + rotation}deg`;
|
||||
});
|
||||
|
||||
const layerStyle = {
|
||||
width: size,
|
||||
height: size,
|
||||
transform: [
|
||||
{
|
||||
rotate: progress.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [`${initStart + 30 + 15}deg`, `${2 * (360 + initStart)}deg`],
|
||||
|
||||
// outputRange: [`${0 + 30 + 15}deg`, `${2 * 360 + 30 + 15}deg`],
|
||||
}),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const viewportStyle = {
|
||||
width: size,
|
||||
height: size,
|
||||
transform: [
|
||||
{
|
||||
translateY: index ? -size / 2 : 0,
|
||||
},
|
||||
{
|
||||
rotate: progress.interpolate({ inputRange, outputRange }),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const containerStyle = {
|
||||
width: !animating ? 300 : size,
|
||||
height: !animating ? 300 : size / 2,
|
||||
overflow: 'hidden',
|
||||
};
|
||||
|
||||
const offsetStyle = index ? { top: size / 2 } : null;
|
||||
|
||||
const lineStyle = {
|
||||
width: size,
|
||||
height: size,
|
||||
borderColor: color,
|
||||
borderWidth: breadth || size / 10,
|
||||
borderRadius: size / 2,
|
||||
};
|
||||
|
||||
return (
|
||||
<Animated.View style={styles.layer} {...{ key: index }}>
|
||||
<Animated.View style={layerStyle}>
|
||||
<Animated.View style={[containerStyle, offsetStyle]} collapsable={false}>
|
||||
<Animated.View style={viewportStyle}>
|
||||
<Animated.View style={containerStyle} collapsable={false}>
|
||||
<Animated.View style={lineStyle} />
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
style,
|
||||
size: width,
|
||||
size: height,
|
||||
animationDuration,
|
||||
interaction,
|
||||
animating,
|
||||
animationEasing,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<View style={[styles.container, style]}>
|
||||
<Indicator
|
||||
style={{ width, height }}
|
||||
renderComponent={this._renderComponent}
|
||||
interaction={interaction}
|
||||
animationEasing={animationEasing}
|
||||
animationDuration={animationDuration}
|
||||
animating={animating}
|
||||
count={2}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SpinIndicator.defaultProps = {
|
||||
animationDuration: 2400,
|
||||
color: '#1a509a',
|
||||
animating: true,
|
||||
size: 40,
|
||||
initStart: 0,
|
||||
};
|
||||
|
||||
export { SpinIndicator };
|
@ -0,0 +1,15 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
export default StyleSheet.create({
|
||||
container: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
position: 'absolute',
|
||||
},
|
||||
|
||||
layer: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
});
|
@ -1,5 +1,6 @@
|
||||
import { AvatarHeader } from './avatarHeader';
|
||||
import { BasicHeader } from './basicHeader';
|
||||
import { BoostIndicatorAnimation } from './animations';
|
||||
import { BottomTabBar } from './bottomTabBar';
|
||||
import { CheckBox } from './checkbox';
|
||||
import { CircularButton, TextButton, SquareButton } from './buttons';
|
||||
@ -36,6 +37,7 @@ import { SearchInput } from './searchInput';
|
||||
import { SearchModal } from './searchModal';
|
||||
import { SettingsItem } from './settingsItem';
|
||||
import { SideMenu } from './sideMenu';
|
||||
import { SpinIndicator } from './animations';
|
||||
import { SummaryArea, TagArea, TextArea, TitleArea } from './editorElements';
|
||||
import { TabBar } from './tabBar';
|
||||
import { TextInput } from './textInput';
|
||||
@ -46,7 +48,6 @@ import { Upvote } from './upvote';
|
||||
import { UserAvatar } from './userAvatar';
|
||||
import Logo from './logo/logo';
|
||||
import PostButton from './postButton/postButtonView';
|
||||
import SpinGame from './spinGame/view/spinGameView';
|
||||
import ProfileEditForm from './profileEditForm/profileEditFormView';
|
||||
import ScaleSlider from './scaleSlider/scaleSliderView';
|
||||
|
||||
@ -98,6 +99,7 @@ export {
|
||||
ListPlaceHolder,
|
||||
BoostPlaceHolder,
|
||||
NoInternetConnection,
|
||||
BoostIndicatorAnimation,
|
||||
NoPost,
|
||||
PostCardPlaceHolder,
|
||||
PostPlaceHolder,
|
||||
@ -132,7 +134,7 @@ export {
|
||||
LeaderBoard,
|
||||
LoginHeader,
|
||||
Logo,
|
||||
SpinGame,
|
||||
SpinIndicator,
|
||||
MainButton,
|
||||
MarkdownEditor,
|
||||
Modal,
|
||||
|
@ -1,115 +0,0 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Animated, Easing } from 'react-native';
|
||||
import RN from 'react-native/package';
|
||||
|
||||
const [major, minor] = RN.version.split('.').map(item => Number(item));
|
||||
const hasLoopSupport = !major && minor >= 45;
|
||||
|
||||
export default class Indicator extends PureComponent {
|
||||
static defaultProps = {
|
||||
animationEasing: Easing.linear,
|
||||
animationDuration: 1200,
|
||||
|
||||
animating: true,
|
||||
interaction: true,
|
||||
|
||||
count: 1,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.renderComponent = this.renderComponent.bind(this);
|
||||
this.startAnimation = this.startAnimation.bind(this);
|
||||
this.stopAnimation = this.stopAnimation.bind(this);
|
||||
|
||||
this.state = {
|
||||
progress: new Animated.Value(0),
|
||||
};
|
||||
|
||||
this.mounted = false;
|
||||
}
|
||||
|
||||
startAnimation({ finished } = {}) {
|
||||
const { progress } = this.state;
|
||||
const { interaction, animationEasing, animationDuration } = this.props;
|
||||
|
||||
if (!this.mounted || false === finished) {
|
||||
return;
|
||||
}
|
||||
|
||||
const animation = Animated.timing(progress, {
|
||||
duration: animationDuration,
|
||||
easing: animationEasing,
|
||||
useNativeDriver: true,
|
||||
isInteraction: interaction,
|
||||
toValue: 1,
|
||||
});
|
||||
|
||||
if (hasLoopSupport) {
|
||||
Animated.loop(animation).start();
|
||||
} else {
|
||||
progress.setValue(0);
|
||||
animation.start(this.startAnimation);
|
||||
}
|
||||
|
||||
this.setState({ animation });
|
||||
}
|
||||
|
||||
stopAnimation() {
|
||||
const { animation } = this.state;
|
||||
|
||||
if (null == animation) {
|
||||
return;
|
||||
}
|
||||
|
||||
animation.stop();
|
||||
|
||||
this.setState({ animation: null });
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { animating } = this.props;
|
||||
|
||||
this.mounted = true;
|
||||
|
||||
if (animating) {
|
||||
this.startAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.mounted = false;
|
||||
}
|
||||
|
||||
componentWillReceiveProps(props) {
|
||||
const { animating } = this.props;
|
||||
|
||||
if (animating ^ props.animating) {
|
||||
if (animating) {
|
||||
this.stopAnimation();
|
||||
} else {
|
||||
this.startAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderComponent(undefined, index) {
|
||||
const { progress } = this.state;
|
||||
const { renderComponent, count } = this.props;
|
||||
|
||||
if ('function' === typeof renderComponent) {
|
||||
return renderComponent({ index, count, progress });
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { count, ...props } = this.props;
|
||||
|
||||
return (
|
||||
<Animated.View {...props}>{Array.from(new Array(count), this.renderComponent)}</Animated.View>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
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,286 +0,0 @@
|
||||
// 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;
|
||||
|
||||
import React, { PureComponent } from 'react';
|
||||
import { View, Animated, Easing } from 'react-native';
|
||||
|
||||
import Indicator from './indicator';
|
||||
import styles from './styles';
|
||||
|
||||
export default class MaterialIndicator extends PureComponent {
|
||||
static defaultProps = {
|
||||
animationDuration: 2400,
|
||||
|
||||
color: 'rgb(0, 0, 0)',
|
||||
size: 40,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.renderComponent = this.renderComponent.bind(this);
|
||||
}
|
||||
|
||||
renderComponent({ index, count, progress }) {
|
||||
const { size, color, animationDuration } = this.props;
|
||||
|
||||
const frames = (60 * animationDuration) / 1000;
|
||||
const easing = Easing.bezier(0.4, 0.0, 0.7, 1.0);
|
||||
|
||||
const inputRange = Array.from(
|
||||
new Array(frames),
|
||||
(undefined, frameIndex) => frameIndex / (frames - 1),
|
||||
);
|
||||
|
||||
const outputRange = Array.from(new Array(frames), (undefined, frameIndex) => {
|
||||
let progress = (2 * frameIndex) / (frames - 1);
|
||||
const rotation = index ? +(360 - 15) : -(180 - 15);
|
||||
|
||||
if (progress > 1.0) {
|
||||
progress = 2.0 - progress;
|
||||
}
|
||||
|
||||
const direction = index ? -1 : +1;
|
||||
|
||||
return direction * (180 - 30) * easing(progress) + rotation + 'deg';
|
||||
});
|
||||
|
||||
const layerStyle = {
|
||||
width: size,
|
||||
height: size,
|
||||
transform: [
|
||||
{
|
||||
rotate: progress.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0 + 30 + 15 + 'deg', 2 * 360 + 30 + 15 + 'deg'],
|
||||
}),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const viewportStyle = {
|
||||
width: size,
|
||||
height: size,
|
||||
transform: [
|
||||
{
|
||||
translateY: index ? -size / 2 : 0,
|
||||
},
|
||||
{
|
||||
rotate: progress.interpolate({ inputRange, outputRange }),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const containerStyle = {
|
||||
width: size,
|
||||
height: size / 2,
|
||||
overflow: 'hidden',
|
||||
};
|
||||
|
||||
const offsetStyle = index ? { top: size / 2 } : null;
|
||||
|
||||
const lineStyle = {
|
||||
width: size,
|
||||
height: size,
|
||||
borderColor: color,
|
||||
borderWidth: size / 10,
|
||||
borderRadius: size / 2,
|
||||
};
|
||||
|
||||
return (
|
||||
<Animated.View style={styles.layer} {...{ key: index }}>
|
||||
<Animated.View style={layerStyle}>
|
||||
<Animated.View style={[containerStyle, offsetStyle]} collapsable={false}>
|
||||
<Animated.View style={viewportStyle}>
|
||||
<Animated.View style={containerStyle} collapsable={false}>
|
||||
<Animated.View style={lineStyle} />
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
</Animated.View>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { style, size: width, size: height, ...props } = this.props;
|
||||
|
||||
return (
|
||||
<View style={[styles.container, style]}>
|
||||
<Indicator
|
||||
style={{ width, height }}
|
||||
renderComponent={this.renderComponent}
|
||||
{...props}
|
||||
count={2}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
// import { StyleSheet } from 'react-native';
|
||||
|
||||
// const styles = StyleSheet.create({
|
||||
// container: {
|
||||
// justifyContent: 'center',
|
||||
// alignItems: 'center',
|
||||
// },
|
||||
// marker: {
|
||||
// position: 'absolute',
|
||||
// },
|
||||
// });
|
||||
|
||||
// export default styles;
|
||||
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
export default StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
|
||||
layer: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
});
|
@ -119,9 +119,9 @@ class BoostContainer extends Component {
|
||||
_buyItem = async sku => {
|
||||
const { navigation } = this.props;
|
||||
|
||||
await this.setState({ isProcessing: true });
|
||||
|
||||
if (sku !== 'freePoints') {
|
||||
await this.setState({ isProcessing: true });
|
||||
|
||||
try {
|
||||
RNIap.requestPurchase(sku, false);
|
||||
} catch (err) {
|
||||
|
@ -1,15 +1,13 @@
|
||||
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';
|
||||
import { TouchableOpacity, Text, View } from 'react-native';
|
||||
|
||||
// Container
|
||||
import { PointsContainer } from '../../../containers';
|
||||
|
||||
// Components
|
||||
import { BasicHeader } from '../../../components/basicHeader';
|
||||
import { SpinGame } from '../../../components';
|
||||
import { BoostIndicatorAnimation, MainButton } from '../../../components';
|
||||
|
||||
// Styles
|
||||
import styles from './freeEstmStyles';
|
||||
@ -23,97 +21,50 @@ class FreeEstmScreen extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
rouletteState: '',
|
||||
option: '',
|
||||
rouletteCustomState: 'stop',
|
||||
optionCustom: '',
|
||||
isSpinning: false,
|
||||
spinRight: 1,
|
||||
};
|
||||
}
|
||||
|
||||
_onRotateChange(state) {
|
||||
this.setState({
|
||||
rouletteState: state,
|
||||
});
|
||||
}
|
||||
_handleOnSpinPress = () => {
|
||||
const { spinRight } = this.state;
|
||||
|
||||
_onRotate(option) {
|
||||
this.setState({
|
||||
option: option.index,
|
||||
isSpinning: true,
|
||||
spinRight: spinRight - 1,
|
||||
});
|
||||
}
|
||||
|
||||
_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 { isSpinning, spinRight } = 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>{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 style={styles.textWrapper}>
|
||||
{!isSpinning && (
|
||||
<Fragment>
|
||||
<Text style={styles.count}>{spinRight}</Text>
|
||||
<Text style={styles.countDesc}>Spin Left</Text>
|
||||
</Fragment>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.spinnerWrapper}>
|
||||
<BoostIndicatorAnimation isSpinning={isSpinning} />
|
||||
<View style={{ flex: 1 }}>
|
||||
{!isSpinning && (
|
||||
<MainButton
|
||||
style={{ marginTop: 50 }}
|
||||
onPress={this._handleOnSpinPress}
|
||||
text="SPIN & WIN"
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</Fragment>
|
||||
)}
|
||||
|
@ -4,6 +4,25 @@ export default EStyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '$primaryBackgroundColor',
|
||||
alignItems: 'center',
|
||||
},
|
||||
textWrapper: {
|
||||
flex: 0.2,
|
||||
backgroundColor: '$primaryBackgroundColor',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
count: {
|
||||
fontSize: 72,
|
||||
fontWeight: '700',
|
||||
color: '$primaryDarkGray',
|
||||
},
|
||||
countDesc: {
|
||||
color: '$primaryDarkGray',
|
||||
fontSize: 16,
|
||||
fontWeight: '700',
|
||||
},
|
||||
spinnerWrapper: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 141 KiB |
Loading…
Reference in New Issue
Block a user