application-amicale/src/components/Mascot/Mascot.js

249 lines
8.2 KiB
JavaScript

// @flow
import * as React from 'react';
import * as Animatable from "react-native-animatable";
import {Image, TouchableWithoutFeedback, View} from "react-native";
type Props = {
size: number,
emotion: number,
animated: boolean,
entryAnimation: Animatable.AnimatableProperties | null,
loopAnimation: Animatable.AnimatableProperties | null,
onPress?: (viewRef: AnimatableViewRef) => null,
onLongPress?: (viewRef: AnimatableViewRef) => null,
}
type State = {
currentEmotion: number,
}
export type AnimatableViewRef = {current: null | Animatable.View};
const MASCOT_IMAGE = require("../../../assets/mascot/mascot.png");
const MASCOT_EYES_NORMAL = require("../../../assets/mascot/mascot_eyes_normal.png");
const MASCOT_EYES_GIRLY = require("../../../assets/mascot/mascot_eyes_girly.png");
const MASCOT_EYES_CUTE = require("../../../assets/mascot/mascot_eyes_cute.png");
const MASCOT_EYES_WINK = require("../../../assets/mascot/mascot_eyes_wink.png");
const MASCOT_EYES_HEART = require("../../../assets/mascot/mascot_eyes_heart.png");
const MASCOT_EYES_ANGRY = require("../../../assets/mascot/mascot_eyes_angry.png");
const MASCOT_GLASSES = require("../../../assets/mascot/mascot_glasses.png");
const MASCOT_SUNGLASSES = require("../../../assets/mascot/mascot_sunglasses.png");
export const EYE_STYLE = {
NORMAL: 0,
GIRLY: 2,
CUTE: 3,
WINK: 4,
HEART: 5,
ANGRY: 6,
}
const GLASSES_STYLE = {
NORMAL: 0,
COOl: 1
}
export const MASCOT_STYLE = {
NORMAL: 0,
HAPPY: 1,
GIRLY: 2,
WINK: 3,
CUTE: 4,
INTELLO: 5,
LOVE: 6,
COOL: 7,
ANGRY: 8,
};
class Mascot extends React.Component<Props, State> {
state = {
currentEmotion: this.props.emotion
}
static defaultProps = {
animated: false,
entryAnimation: {
useNativeDriver: true,
animation: "rubberBand",
duration: 2000,
},
loopAnimation: {
useNativeDriver: true,
animation: "swing",
duration: 2000,
iterationDelay: 250,
iterationCount: "infinite",
},
clickAnimation: {
useNativeDriver: true,
animation: "rubberBand",
duration: 2000,
},
}
viewRef: AnimatableViewRef;
eyeList: { [key: number]: number | string };
glassesList: { [key: number]: number | string };
onPress: (viewRef: AnimatableViewRef) => null;
onLongPress: (viewRef: AnimatableViewRef) => null;
constructor(props: Props) {
super(props);
this.viewRef = React.createRef();
this.eyeList = {};
this.glassesList = {};
this.eyeList[EYE_STYLE.NORMAL] = MASCOT_EYES_NORMAL;
this.eyeList[EYE_STYLE.GIRLY] = MASCOT_EYES_GIRLY;
this.eyeList[EYE_STYLE.CUTE] = MASCOT_EYES_CUTE;
this.eyeList[EYE_STYLE.WINK] = MASCOT_EYES_WINK;
this.eyeList[EYE_STYLE.HEART] = MASCOT_EYES_HEART;
this.eyeList[EYE_STYLE.ANGRY] = MASCOT_EYES_ANGRY;
this.glassesList[GLASSES_STYLE.NORMAL] = MASCOT_GLASSES;
this.glassesList[GLASSES_STYLE.COOl] = MASCOT_SUNGLASSES;
if (this.props.onPress == null) {
this.onPress = (viewRef: AnimatableViewRef) => {
if (viewRef.current != null) {
this.setState({currentEmotion: MASCOT_STYLE.LOVE});
viewRef.current.rubberBand(1500).then(() => {
this.setState({currentEmotion: this.props.emotion});
});
}
return null;
}
} else
this.onPress = this.props.onPress;
if (this.props.onLongPress == null) {
this.onLongPress = (viewRef: AnimatableViewRef) => {
if (viewRef.current != null) {
this.setState({currentEmotion: MASCOT_STYLE.ANGRY});
viewRef.current.tada(1000).then(() => {
this.setState({currentEmotion: this.props.emotion});
});
}
return null;
}
} else
this.onLongPress = this.props.onLongPress;
}
getGlasses(style: number) {
const glasses = this.glassesList[style];
return <Image
key={"glasses"}
source={glasses != null ? glasses : this.glassesList[GLASSES_STYLE.NORMAL]}
style={{
position: "absolute",
top: "15%",
left: 0,
width: this.props.size,
height: this.props.size,
}}
/>
}
getEye(style: number, isRight: boolean, rotation: string="0deg") {
const eye = this.eyeList[style];
return <Image
key={isRight ? "right" : "left"}
source={eye != null ? eye : this.eyeList[EYE_STYLE.NORMAL]}
style={{
position: "absolute",
top: "15%",
left: isRight ? "-11%" : "11%",
width: this.props.size,
height: this.props.size,
transform: [{rotateY: rotation}]
}}
/>
}
getEyes(emotion: number) {
let final = [];
final.push(<View
key={"container"}
style={{
position: "absolute",
width: this.props.size,
height: this.props.size,
}}/>);
if (emotion === MASCOT_STYLE.CUTE) {
final.push(this.getEye(EYE_STYLE.CUTE, true));
final.push(this.getEye(EYE_STYLE.CUTE, false));
} else if (emotion === MASCOT_STYLE.GIRLY) {
final.push(this.getEye(EYE_STYLE.GIRLY, true));
final.push(this.getEye(EYE_STYLE.GIRLY, false));
} else if (emotion === MASCOT_STYLE.HAPPY) {
final.push(this.getEye(EYE_STYLE.WINK, true));
final.push(this.getEye(EYE_STYLE.WINK, false));
} else if (emotion === MASCOT_STYLE.WINK) {
final.push(this.getEye(EYE_STYLE.WINK, true));
final.push(this.getEye(EYE_STYLE.NORMAL, false));
} else if (emotion === MASCOT_STYLE.LOVE) {
final.push(this.getEye(EYE_STYLE.HEART, true));
final.push(this.getEye(EYE_STYLE.HEART, false));
} else if (emotion === MASCOT_STYLE.ANGRY) {
final.push(this.getEye(EYE_STYLE.ANGRY, true));
final.push(this.getEye(EYE_STYLE.ANGRY, false, "180deg"));
} else if (emotion === MASCOT_STYLE.COOL) {
final.push(this.getGlasses(GLASSES_STYLE.COOl));
} else {
final.push(this.getEye(EYE_STYLE.NORMAL, true));
final.push(this.getEye(EYE_STYLE.NORMAL, false));
}
if (emotion === MASCOT_STYLE.INTELLO) { // Needs to have normal eyes behind the glasses
final.push(this.getGlasses(GLASSES_STYLE.NORMAL));
}
final.push(<View key={"container2"}/>);
return final;
}
render() {
const size = this.props.size;
const entryAnimation = this.props.animated ? this.props.entryAnimation : null;
const loopAnimation = this.props.animated ? this.props.loopAnimation : null;
return (
<Animatable.View
style={{
width: size,
height: size,
}}
{...entryAnimation}
>
<TouchableWithoutFeedback
onPress={() => this.onPress(this.viewRef)}
onLongPress={() => this.onLongPress(this.viewRef)}
>
<Animatable.View
ref={this.viewRef}
>
<Animatable.View
{...loopAnimation}
>
<Image
source={MASCOT_IMAGE}
style={{
width: size,
height: size,
}}
/>
{this.getEyes(this.state.currentEmotion)}
</Animatable.View>
</Animatable.View>
</TouchableWithoutFeedback>
</Animatable.View>
);
}
}
export default Mascot;