add initial animation on load for first slide

This commit is contained in:
Pablo Velez Vidal 2022-11-04 14:21:50 +01:00
parent d921da0e9d
commit 63cc3e7413
3 changed files with 82 additions and 8 deletions

View file

@ -3,8 +3,7 @@
import React from 'react';
import {Pressable, useWindowDimensions, View} from 'react-native';
import Button from 'react-native-button';
import Animated, {interpolate, useAnimatedStyle} from 'react-native-reanimated';
import Animated, {Extrapolate, interpolate, useAnimatedStyle} from 'react-native-reanimated';
import CompassIcon from '@app/components/compass_icon';
import FormattedText from '@app/components/formatted_text';
@ -58,6 +57,7 @@ const FooterButtons = ({
scrollX.value,
inputRange,
[BUTTON_SIZE, isLastSlide ? width * 0.8 : BUTTON_SIZE, width * 0.8],
Extrapolate.CLAMP,
);
return {width: needToAnimate ? interpolatedWidth : BUTTON_SIZE};
@ -68,6 +68,7 @@ const FooterButtons = ({
scrollX.value,
inputRange,
[isPenultimateSlide ? 1 : 0, 1, 0],
Extrapolate.CLAMP,
);
return {opacity: needToAnimate ? interpolatedScale : 1};
@ -78,6 +79,7 @@ const FooterButtons = ({
scrollX.value,
inputRange,
[1, (isLastSlide ? 0 : 1), 0],
Extrapolate.CLAMP,
);
return {opacity: needToAnimate ? interpolatedScale : 1};

View file

@ -93,7 +93,7 @@ const Onboarding = ({
showsHorizontalScrollIndicator={false}
pagingEnabled={true}
bounces={false}
onMomentumScrollEnd={handleScroll}
onScroll={handleScroll}
ref={slidesRef}
>
{slidesData.map((item, index) => {

View file

@ -1,9 +1,9 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import React, { useEffect, useState } from 'react';
import {View, useWindowDimensions} from 'react-native';
import Animated, {Extrapolate, interpolate, useAnimatedStyle} from 'react-native-reanimated';
import Animated, {Extrapolate, interpolate, useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
@ -31,6 +31,10 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
fontFirstTitle: {
fontSize: 66,
},
firstSlideInitialPosition: {
left: 200,
opacity: 0,
},
description: {
fontWeight: '400',
fontSize: 16,
@ -56,8 +60,59 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
const SlideItem = ({theme, item, scrollX, index}: Props) => {
const {width} = useWindowDimensions();
const styles = getStyleSheet(theme);
const FIRST_SLIDE = 0;
const SvgImg = item.image;
/**
* Code used to animate the first image load
*/
const FIRST_LOAD_ELEMENTS_POSITION = 400;
const [firstLoad, setFirstLoad] = useState(true);
const initialImagePosition = useSharedValue(FIRST_LOAD_ELEMENTS_POSITION);
const initialTitlePosition = useSharedValue(FIRST_LOAD_ELEMENTS_POSITION);
const initialDescriptionPosition = useSharedValue(FIRST_LOAD_ELEMENTS_POSITION);
const initialElementsOpacity = useSharedValue(0);
useEffect(() => {
if (index === FIRST_SLIDE) {
initialImagePosition.value = withTiming(0, {duration: 1000});
initialTitlePosition.value = withTiming(0, {duration: 1250});
initialDescriptionPosition.value = withTiming(0, {duration: 1500});
initialElementsOpacity.value = withTiming(1, {duration: 1500});
setFirstLoad(false);
}
}, []);
const translateFirstImageOnLoad = useAnimatedStyle(() => {
return {
transform: [{
translateX: initialImagePosition.value,
}],
opacity: initialElementsOpacity.value,
};
});
const translateFirstTitleOnLoad = useAnimatedStyle(() => {
return {
transform: [{
translateX: initialTitlePosition.value,
}],
opacity: initialElementsOpacity.value,
};
});
const translateFirstDescriptionOnLoad = useAnimatedStyle(() => {
return {
transform: [{
translateX: initialDescriptionPosition.value,
}],
opacity: initialElementsOpacity.value,
};
});// end of code for animating first image load
const inputRange = [(index - 1) * width, index * width, (index + 1) * width];
const translateImage = useAnimatedStyle(() => {
@ -119,7 +174,11 @@ const SlideItem = ({theme, item, scrollX, index}: Props) => {
return (
<View style={[styles.itemContainer, {width}]}>
<Animated.View
style={[translateImage]}
style={[
translateImage,
translateFirstImageOnLoad,
(index === FIRST_SLIDE && firstLoad ? styles.firstSlideInitialPosition : undefined),
]}
>
<SvgImg
style={[styles.image, {
@ -130,12 +189,25 @@ const SlideItem = ({theme, item, scrollX, index}: Props) => {
</Animated.View>
<View style={{flex: 0.3}}>
<Animated.Text
style={[styles.title, (index === 0 ? styles.fontFirstTitle : styles.fontTitle), translateTitle, opacity]}
style={[
styles.title,
(index === FIRST_SLIDE ? styles.fontFirstTitle : styles.fontTitle),
translateTitle,
opacity,
translateFirstTitleOnLoad,
(index === FIRST_SLIDE && firstLoad ? styles.firstSlideInitialPosition : undefined),
]}
>
{item.title}
</Animated.Text>
<Animated.Text
style={[styles.description, translateDescription, opacity]}
style={[
styles.description,
translateDescription,
opacity,
(index === FIRST_SLIDE && firstLoad ? styles.firstSlideInitialPosition : undefined),
translateFirstDescriptionOnLoad,
]}
>
{item.description}
</Animated.Text>