react-native-walkthrough-swiper
Version:
A walkthrough swiper component for React-Native. Can be used in onboarding/walkthrough screens. Uses Reanimated API to create smooth animations.
131 lines • 4.1 kB
JavaScript
import React, { useEffect, useRef } from 'react';
import { StyleSheet, Text, View, Dimensions } from 'react-native';
import Reanimated, { Easing, useAnimatedStyle, useSharedValue, withDelay, withSpring, withTiming } from 'react-native-reanimated';
const width = Dimensions.get('window').width;
const TEXT_OUT_DURATION = 160;
const TEXT_OUT_OPACITY_DURATION = 100;
const TEXT_IN_DURATION = 200;
const SUBTITLE_IN_DELAY = 40;
const ElasticText = _ref => {
let {
data,
currentSlide,
titleStyle,
subTitleStyle
} = _ref;
const oldSlide = useRef(currentSlide);
const animationVars = useRef(data.map(() => ({
title: {
alpha: useSharedValue(0),
x: useSharedValue(0)
},
subtitle: {
alpha: useSharedValue(0),
x: useSharedValue(0)
}
})));
useEffect(() => {
moveText(oldSlide.current, currentSlide);
oldSlide.current = currentSlide;
}, [currentSlide]);
const moveText = (prev, active) => {
const direction = active < prev ? -1 : 1;
const textInSpring = {
damping: 14,
mass: 1,
stiffness: 100
};
data.forEach((_, index) => {
const {
title,
subtitle
} = animationVars.current[index];
title.x.value = withTiming(direction * (index === prev ? -1 : 1) * width, {
easing: Easing.inOut(Easing.linear),
duration: TEXT_OUT_DURATION
});
subtitle.x.value = withTiming(direction * (index === prev ? -1 : 1) * width, {
easing: Easing.inOut(Easing.linear),
duration: TEXT_OUT_DURATION
});
title.alpha.value = withTiming(0, {
easing: Easing.inOut(Easing.linear),
duration: TEXT_OUT_OPACITY_DURATION
});
subtitle.alpha.value = withTiming(0, {
easing: Easing.inOut(Easing.linear),
duration: TEXT_OUT_OPACITY_DURATION
});
title.x.value = withSpring(index === active ? 0 : direction * width, textInSpring);
subtitle.x.value = withDelay(SUBTITLE_IN_DELAY, withSpring(index === active ? 0 : direction * width, textInSpring));
title.alpha.value = withTiming(index === active ? 1 : 0, {
easing: Easing.inOut(Easing.exp),
duration: TEXT_IN_DURATION
});
subtitle.alpha.value = withDelay(SUBTITLE_IN_DELAY, withTiming(index === active ? 1 : 0, {
easing: Easing.inOut(Easing.exp),
duration: TEXT_IN_DURATION
}));
});
};
return /*#__PURE__*/React.createElement(React.Fragment, null, data.map((slide, index) => {
const {
title,
subtitle
} = animationVars.current[index];
const titleAnimatedStyle = useAnimatedStyle(() => {
const transX = title.x.value;
return {
transform: [{
translateX: transX
}],
opacity: title.alpha.value
};
});
const subtitleAnimatedStyle = useAnimatedStyle(() => {
const transX = subtitle.x.value;
return {
transform: [{
translateX: -1 * transX
}],
opacity: subtitle.alpha.value
};
});
return /*#__PURE__*/React.createElement(View, {
style: styles.container,
key: `content_${index}`
}, /*#__PURE__*/React.createElement(Reanimated.View, {
key: `title_${index}`,
style: [{
width: width - 40
}, titleAnimatedStyle]
}, /*#__PURE__*/React.createElement(Text, {
style: [{
fontSize: 32,
marginBottom: 12
}, titleStyle]
}, slide.title)), /*#__PURE__*/React.createElement(Reanimated.View, {
key: `subtitle_${index}`,
style: [styles.widthWithMargin, subtitleAnimatedStyle]
}, /*#__PURE__*/React.createElement(Text, {
style: [{
fontSize: 14.4
}, subTitleStyle]
}, slide.subTitle)));
}));
};
const styles = StyleSheet.create({
container: {
position: 'absolute',
flexDirection: 'column',
alignItems: 'center',
alignSelf: 'center',
width: width - 40,
bottom: 72
},
widthWithMargin: {
width: width - 40
}
});
export default /*#__PURE__*/React.memo(ElasticText);
//# sourceMappingURL=ElasticText.js.map