import {I18nManager} from 'react-native';
import getSceneIndicesForInterpolationInputRange from
'../../utils/getSceneIndicesForInterpolationInputRange';
/**
* 工具类:构建 card stack 中 card 的样式,在屏幕切换时使用的插值器 screenInterpolator
* Utility that builds the style for the card in the cards stack.
*
* card stack, 卡片栈, 可以理解成将很多卡片通过栈管理起来,
* 栈顶的那个卡片就是 Focused Card , 也就是用户当前正在操作的那个场景屏幕的卡片
*
* +------------+
* +-+ |
* +-+ | |
* | | | |
* | | | 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; // 不透明度,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.
* 同时动画操作 opacity 和 translateX
* 1.iOS 上的标准样式:屏幕自右向左滑出,
* 2.在 Android 上也可以使用
* @param props
* @return {*}
*/
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],
});
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],
});
const translateY = 0;
return {
opacity,
transform: [{translateX}, {translateY}],
};
}
/**
* Standard iOS-style slide in from the bottom (used for modals).
* 同时动画操作 opacity 和 translateY
* 1. iOS 上标准的模态(modal)屏幕的弹出方式:自底向上弹出
* 2. Android 上也可以使用
*
* @param props
* @return {*}
*/
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],
});
const height = layout.initHeight;
const translateY = position.interpolate({
inputRange: [first, index, last],
outputRange: [height, 0, 0],
});
const translateX = 0;
return {
opacity,
transform: [{translateX}, {translateY}],
};
}
/**
* Standard Android-style fade in from the bottom.
* 同时动画操作 opacity 和 translateY
* 1. Android 上标准的屏幕从底部淡入的方式
* 2. iOS 上也可以使用
* @param props
* @return {*}
*/
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],
});
const translateY = position.interpolate({
inputRange,
outputRange: [50, 0, 0, 0],
});
const translateX = 0;
return {
opacity,
transform: [{translateX}, {translateY}],
};
}
/**
* fadeIn and fadeOut
* 淡入和淡出,元素坐标无变化,透明度(opacity)变化
* @param props
* @return {*}
*/
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],
});
return {
opacity,
};
}
/**
* 是否可以使用原生动画驱动,
* iOS和Android平台上都可以使用原生动画驱动,所以此值总是返回 true,
* @return {boolean}
*/
function canUseNativeDriver() {
// The native driver can be enabled for this interpolator animating
// opacity, translateX, and translateY is supported by the native animation
// driver on iOS and Android.
return true;
}
/**
* 导出所定义的屏幕插值器 screenInterpolator 和其他工具函数
*/
export default {
forHorizontal,
forVertical,
forFadeFromBottomAndroid,
forFade,
canUseNativeDriver,
};
React Navigation源代码阅读 : views/CardStack/CardStackStyleInterpolator.js
猜你喜欢
转载自blog.csdn.net/andy_zhang2007/article/details/80494169
今日推荐
周排行