mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-02-13 17:47:32 +08:00
175 lines
4.0 KiB
JavaScript
175 lines
4.0 KiB
JavaScript
import { I18nManager } from 'react-native';
|
|
import getSceneIndicesForInterpolationInputRange from '../../utils/getSceneIndicesForInterpolationInputRange';
|
|
|
|
/**
|
|
* Utility that builds the style for the card in the cards stack.
|
|
*
|
|
* +------------+
|
|
* +-+ |
|
|
* +-+ | |
|
|
* | | | |
|
|
* | | | Focused |
|
|
* | | | Card |
|
|
* | | | |
|
|
* +-+ | |
|
|
* +-+ |
|
|
* +------------+
|
|
*/
|
|
|
|
/**
|
|
* Render the initial style when the initial layout isn't measured yet.
|
|
*/
|
|
function forInitial(props) {
|
|
const { navigation, scene } = props;
|
|
|
|
const focused = navigation.state.index === scene.index;
|
|
const opacity = focused ? 1 : 0;
|
|
// If not focused, move the scene far away.
|
|
const translate = focused ? 0 : 1000000;
|
|
return {
|
|
opacity,
|
|
transform: [{ translateX: translate }, { translateY: translate }],
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Standard iOS-style slide in from the right.
|
|
*/
|
|
function forHorizontal(props) {
|
|
const { layout, position, scene } = props;
|
|
|
|
if (!layout.isMeasured) {
|
|
return forInitial(props);
|
|
}
|
|
const interpolate = getSceneIndicesForInterpolationInputRange(props);
|
|
|
|
if (!interpolate) return { opacity: 0 };
|
|
|
|
const { first, last } = interpolate;
|
|
const index = scene.index;
|
|
const opacity = position.interpolate({
|
|
inputRange: [first, first + 0.01, index, last - 0.01, last],
|
|
outputRange: [0, 1, 1, 0.85, 0],
|
|
extrapolate: 'clamp',
|
|
});
|
|
|
|
const width = layout.initWidth;
|
|
const translateX = position.interpolate({
|
|
inputRange: [first, index, last],
|
|
outputRange: I18nManager.isRTL
|
|
? [-width, 0, width * 0.3]
|
|
: [width, 0, width * -0.3],
|
|
extrapolate: 'clamp',
|
|
});
|
|
const translateY = 0;
|
|
|
|
return {
|
|
opacity,
|
|
transform: [{ translateX }, { translateY }],
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Standard iOS-style slide in from the bottom (used for modals).
|
|
*/
|
|
function forVertical(props) {
|
|
const { layout, position, scene } = props;
|
|
|
|
if (!layout.isMeasured) {
|
|
return forInitial(props);
|
|
}
|
|
const interpolate = getSceneIndicesForInterpolationInputRange(props);
|
|
|
|
if (!interpolate) return { opacity: 0 };
|
|
|
|
const { first, last } = interpolate;
|
|
const index = scene.index;
|
|
const opacity = position.interpolate({
|
|
inputRange: [first, first + 0.01, index, last - 0.01, last],
|
|
outputRange: [0, 1, 1, 0.85, 0],
|
|
extrapolate: 'clamp',
|
|
});
|
|
|
|
const height = layout.initHeight;
|
|
const translateY = position.interpolate({
|
|
inputRange: [first, index, last],
|
|
outputRange: [height, 0, 0],
|
|
extrapolate: 'clamp',
|
|
});
|
|
const translateX = 0;
|
|
|
|
return {
|
|
opacity,
|
|
transform: [{ translateX }, { translateY }],
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Standard Android-style fade in from the bottom.
|
|
*/
|
|
function forFadeFromBottomAndroid(props) {
|
|
const { layout, position, scene } = props;
|
|
|
|
if (!layout.isMeasured) {
|
|
return forInitial(props);
|
|
}
|
|
const interpolate = getSceneIndicesForInterpolationInputRange(props);
|
|
|
|
if (!interpolate) return { opacity: 0 };
|
|
|
|
const { first, last } = interpolate;
|
|
const index = scene.index;
|
|
const inputRange = [first, index, last - 0.01, last];
|
|
|
|
const opacity = position.interpolate({
|
|
inputRange,
|
|
outputRange: [0, 1, 1, 0],
|
|
extrapolate: 'clamp',
|
|
});
|
|
|
|
const translateY = position.interpolate({
|
|
inputRange,
|
|
outputRange: [50, 0, 0, 0],
|
|
extrapolate: 'clamp',
|
|
});
|
|
const translateX = 0;
|
|
|
|
return {
|
|
opacity,
|
|
transform: [{ translateX }, { translateY }],
|
|
};
|
|
}
|
|
|
|
/**
|
|
* fadeIn and fadeOut
|
|
*/
|
|
function forFade(props) {
|
|
const { layout, position, scene } = props;
|
|
|
|
if (!layout.isMeasured) {
|
|
return forInitial(props);
|
|
}
|
|
const interpolate = getSceneIndicesForInterpolationInputRange(props);
|
|
|
|
if (!interpolate) return { opacity: 0 };
|
|
|
|
const { first, last } = interpolate;
|
|
const index = scene.index;
|
|
const opacity = position.interpolate({
|
|
inputRange: [first, index, last],
|
|
outputRange: [0, 1, 1],
|
|
extrapolate: 'clamp',
|
|
});
|
|
|
|
return {
|
|
opacity,
|
|
};
|
|
}
|
|
|
|
export default {
|
|
forHorizontal,
|
|
forVertical,
|
|
forFadeFromBottomAndroid,
|
|
forFade,
|
|
};
|