Improved mascot style management

This commit is contained in:
Arnaud Vergnet 2020-07-20 16:36:16 +02:00
parent de41a57930
commit 0ed3122dcf
6 changed files with 119 additions and 102 deletions

View file

@ -3,9 +3,10 @@
import * as React from 'react';
import * as Animatable from "react-native-animatable";
import {Image, TouchableWithoutFeedback, View} from "react-native";
import type {ViewStyle} from "react-native/Libraries/StyleSheet/StyleSheet";
type Props = {
size: number,
style?: ViewStyle,
emotion: number,
animated: boolean,
entryAnimation: Animatable.AnimatableProperties | null,
@ -116,9 +117,10 @@ class Mascot extends React.Component<Props, State> {
if (this.props.onPress == null) {
this.onPress = (viewRef: AnimatableViewRef) => {
if (viewRef.current != null) {
let ref = viewRef.current;
if (ref != null) {
this.setState({currentEmotion: MASCOT_STYLE.LOVE});
viewRef.current.rubberBand(1500).then(() => {
ref.rubberBand(1500).then(() => {
this.setState({currentEmotion: this.initialEmotion});
});
@ -130,9 +132,10 @@ class Mascot extends React.Component<Props, State> {
if (this.props.onLongPress == null) {
this.onLongPress = (viewRef: AnimatableViewRef) => {
if (viewRef.current != null) {
let ref = viewRef.current;
if (ref != null) {
this.setState({currentEmotion: MASCOT_STYLE.ANGRY});
viewRef.current.tada(1000).then(() => {
ref.tada(1000).then(() => {
this.setState({currentEmotion: this.initialEmotion});
});
@ -153,8 +156,8 @@ class Mascot extends React.Component<Props, State> {
position: "absolute",
top: "15%",
left: 0,
width: this.props.size,
height: this.props.size,
width: "100%",
height: "100%",
}}
/>
}
@ -168,8 +171,8 @@ class Mascot extends React.Component<Props, State> {
position: "absolute",
top: "15%",
left: isRight ? "-11%" : "11%",
width: this.props.size,
height: this.props.size,
width: "100%",
height: "100%",
transform: [{rotateY: rotation}]
}}
/>
@ -181,8 +184,8 @@ class Mascot extends React.Component<Props, State> {
key={"container"}
style={{
position: "absolute",
width: this.props.size,
height: this.props.size,
width: "100%",
height: "100%",
}}/>);
if (emotion === MASCOT_STYLE.CUTE) {
final.push(this.getEye(EYE_STYLE.CUTE, true));
@ -217,14 +220,13 @@ class Mascot extends React.Component<Props, State> {
}
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,
aspectRatio: 1,
...this.props.style
}}
{...entryAnimation}
>
@ -241,8 +243,8 @@ class Mascot extends React.Component<Props, State> {
<Image
source={MASCOT_IMAGE}
style={{
width: size,
height: size,
width: "100%",
height:"100%",
}}
/>
{this.getEyes(this.state.currentEmotion)}

View file

@ -160,7 +160,7 @@ class MascotPopup extends React.Component<Props, State> {
duration={this.props.visible ? 1500 : 200}
>
<Mascot
size={this.mascotSize}
style={{width: this.mascotSize}}
animated={true}
emotion={this.props.emotion}
/>
@ -241,15 +241,16 @@ class MascotPopup extends React.Component<Props, State> {
}}>
<View style={{
marginTop: -80,
width: "100%"
}}>
{this.getMascot()}
{this.getSpeechBubble()}
</View>
</View>
</View>
</Portal>
)
;
</View>
</Portal>
)
;
} else
return null;

View file

@ -146,20 +146,27 @@ export default class CustomIntroSlider extends React.Component<Props, State> {
</View>
<Animatable.View
animation={"fadeIn"}>
{index !== 0 && index !== this.introSlides.length -1
? <Animatable.View
animation={"pulse"}
iterationCount={"infinite"}
duration={2000}
{index !== 0 && index !== this.introSlides.length - 1
?
<Mascot
style={{
marginLeft: 30,
marginBottom: 0,
width: 100,
marginTop: -30,
}}>
<Mascot emotion={item.mascotStyle} size={100}/>
</Animatable.View> : null}
}}
emotion={item.mascotStyle}
animated={true}
entryAnimation={{
animation: "slideInLeft",
duration: 500
}}
loopAnimation={{
animation: "pulse",
iterationCount: "infinite",
duration: 2000,
}}
/> : null}
<View style={{
marginLeft: 50,
width: 0,
@ -204,23 +211,23 @@ export default class CustomIntroSlider extends React.Component<Props, State> {
getEndView = () => {
return (
<View style={{flex: 1}}>
<View
style={styles.center}>
<Mascot
size={250}
emotion={MASCOT_STYLE.COOL}
animated={true}
entryAnimation={{
animation: "slideInDown",
duration: 2000,
}}
loopAnimation={{
animation: "pulse",
duration: 2000,
iterationCount: "infinite"
}}
/>
</View>
<Mascot
style={{
...styles.center,
height: "80%"
}}
emotion={MASCOT_STYLE.COOL}
animated={true}
entryAnimation={{
animation: "slideInDown",
duration: 2000,
}}
loopAnimation={{
animation: "pulse",
duration: 2000,
iterationCount: "infinite"
}}
/>
</View>
);
}
@ -228,55 +235,52 @@ export default class CustomIntroSlider extends React.Component<Props, State> {
getWelcomeView = () => {
return (
<View style={{flex: 1}}>
<View
style={styles.center}>
<Mascot
size={250}
emotion={MASCOT_STYLE.NORMAL}
animated={true}
entryAnimation={{
animation: "bounceIn",
duration: 2000,
}}
/>
<Animatable.Text
useNativeDriver={true}
animation={"fadeInUp"}
duration={500}
<Mascot
style={{
...styles.center,
height: "80%"
}}
emotion={MASCOT_STYLE.NORMAL}
animated={true}
entryAnimation={{
animation: "bounceIn",
duration: 2000,
}}
/>
<Animatable.Text
useNativeDriver={true}
animation={"fadeInUp"}
duration={500}
style={{
style={{
color: "#fff",
textAlign: "center",
fontSize: 25,
}}>
PABLO
</Animatable.Text>
<Animatable.View
useNativeDriver={true}
animation={"fadeInUp"}
duration={500}
delay={200}
PABLO
</Animatable.Text>
<Animatable.View
useNativeDriver={true}
animation={"fadeInUp"}
duration={500}
delay={200}
style={{
position: "absolute",
bottom: 30,
right: "20%",
width: 50,
height: 50,
}}>
<MaterialCommunityIcons
style={{
position: "absolute",
top: 210,
left: 160,
width: 50,
height: 50,
}}>
<MaterialCommunityIcons
style={{
marginLeft: "auto",
marginRight: "auto",
marginTop: "auto",
marginBottom: "auto",
transform: [{rotateZ: "70deg"}],
}}
name={"undo"}
color={'#fff'}
size={40}/>
</Animatable.View>
</View>
...styles.center,
transform: [{rotateZ: "70deg"}],
}}
name={"undo"}
color={'#fff'}
size={40}/>
</Animatable.View>
</View>
)
}
@ -403,5 +407,5 @@ const styles = StyleSheet.create({
marginBottom: 'auto',
marginRight: 'auto',
marginLeft: 'auto',
}
},
});

View file

@ -117,8 +117,10 @@ function HomeStackComponent(initialRoute: string | null, defaultData: { [key: st
},
headerTitle: (props) => <View style={{flexDirection: "row"}}>
<Mascot
style={{
width: 50
}}
emotion={MASCOT_STYLE.RANDOM}
size={50}
animated={true}
entryAnimation={{
animation: "bounceIn",

View file

@ -158,15 +158,18 @@ class ProfileScreen extends React.Component<Props, State> {
<Card style={styles.card}>
<Card.Title
title={i18n.t("screens.profile.welcomeTitle", {name: this.data.first_name})}
left={() => <Mascot
emotion={MASCOT_STYLE.COOL}
size={60}
animated={true}
entryAnimation={{
animation: "bounceIn",
duration: 1000
}}
/>}
left={() =>
<Mascot
style={{
width: 60
}}
emotion={MASCOT_STYLE.COOL}
animated={true}
entryAnimation={{
animation: "bounceIn",
duration: 1000
}}
/>}
titleStyle={{marginLeft: 10}}
/>
<Card.Content>

View file

@ -6,7 +6,7 @@ import type {CustomTheme} from "../../../managers/ThemeManager";
import {Button, Headline, withTheme} from "react-native-paper";
import {View} from "react-native";
import i18n from "i18n-js";
import {MASCOT_STYLE} from "../../../components/Mascot/Mascot";
import Mascot, {MASCOT_STYLE} from "../../../components/Mascot/Mascot";
import MascotPopup from "../../../components/Mascot/MascotPopup";
import AsyncStorageManager from "../../../managers/AsyncStorageManager";
@ -36,6 +36,11 @@ class GameStartScreen extends React.Component<Props, State> {
render() {
return (
<View style={{flex: 1}}>
<Mascot emotion={MASCOT_STYLE.NORMAL} style={{
width: "50%",
marginLeft: "auto",
marginRight: "auto",
}}/>
<Headline style={{textAlign: "center"}}>Coucou</Headline>
<Button
mode={"contained"}