@react-navigation/stack
Version:
Stack navigator component for iOS and Android with animated transitions and gestures
253 lines (246 loc) • 6.22 kB
JavaScript
import { Animated, I18nManager } from 'react-native';
const {
add
} = Animated;
/**
* Standard UIKit style animation for the header where the title fades into the back button label.
*/
export function forUIKit(_ref) {
let {
current,
next,
layouts
} = _ref;
const defaultOffset = 100;
const leftSpacing = 27;
// The title and back button title should cross-fade to each other
// When screen is fully open, the title should be in center, and back title should be on left
// When screen is closing, the previous title will animate to back title's position
// And back title will animate to title's position
// We achieve this by calculating the offsets needed to translate title to back title's position and vice-versa
const leftLabelOffset = layouts.leftLabel ? (layouts.screen.width - layouts.leftLabel.width) / 2 - leftSpacing : defaultOffset;
const titleLeftOffset = layouts.title ? (layouts.screen.width - layouts.title.width) / 2 - leftSpacing : defaultOffset;
// When the current title is animating to right, it is centered in the right half of screen in middle of transition
// The back title also animates in from this position
const rightOffset = layouts.screen.width / 4;
const progress = add(current.progress.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolate: 'clamp'
}), next ? next.progress.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolate: 'clamp'
}) : 0);
return {
leftButtonStyle: {
opacity: progress.interpolate({
inputRange: [0.3, 1, 1.5],
outputRange: [0, 1, 0]
})
},
leftLabelStyle: {
transform: [{
translateX: progress.interpolate({
inputRange: [0, 1, 2],
outputRange: I18nManager.getConstants().isRTL ? [-rightOffset, 0, leftLabelOffset] : [leftLabelOffset, 0, -rightOffset]
})
}]
},
rightButtonStyle: {
opacity: progress.interpolate({
inputRange: [0.3, 1, 1.5],
outputRange: [0, 1, 0]
})
},
titleStyle: {
opacity: progress.interpolate({
inputRange: [0, 0.4, 1, 1.5],
outputRange: [0, 0.1, 1, 0]
}),
transform: [{
translateX: progress.interpolate({
inputRange: [0.5, 1, 2],
outputRange: I18nManager.getConstants().isRTL ? [-titleLeftOffset, 0, rightOffset] : [rightOffset, 0, -titleLeftOffset]
})
}]
},
backgroundStyle: {
transform: [{
translateX: progress.interpolate({
inputRange: [0, 1, 2],
outputRange: I18nManager.getConstants().isRTL ? [-layouts.screen.width, 0, layouts.screen.width] : [layouts.screen.width, 0, -layouts.screen.width]
})
}]
}
};
}
/**
* Simple fade animation for the header elements.
*/
export function forFade(_ref2) {
let {
current,
next
} = _ref2;
const progress = add(current.progress.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolate: 'clamp'
}), next ? next.progress.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolate: 'clamp'
}) : 0);
const opacity = progress.interpolate({
inputRange: [0, 1, 2],
outputRange: [0, 1, 0]
});
return {
leftButtonStyle: {
opacity
},
rightButtonStyle: {
opacity
},
titleStyle: {
opacity
},
backgroundStyle: {
opacity: progress.interpolate({
inputRange: [0, 1, 1.9, 2],
outputRange: [0, 1, 1, 0]
})
}
};
}
/**
* Simple translate animation to translate the header to left.
*/
export function forSlideLeft(_ref3) {
let {
current,
next,
layouts: {
screen
}
} = _ref3;
const progress = add(current.progress.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolate: 'clamp'
}), next ? next.progress.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolate: 'clamp'
}) : 0);
const translateX = progress.interpolate({
inputRange: [0, 1, 2],
outputRange: I18nManager.getConstants().isRTL ? [-screen.width, 0, screen.width] : [screen.width, 0, -screen.width]
});
const transform = [{
translateX
}];
return {
leftButtonStyle: {
transform
},
rightButtonStyle: {
transform
},
titleStyle: {
transform
},
backgroundStyle: {
transform
}
};
}
/**
* Simple translate animation to translate the header to right.
*/
export function forSlideRight(_ref4) {
let {
current,
next,
layouts: {
screen
}
} = _ref4;
const progress = add(current.progress.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolate: 'clamp'
}), next ? next.progress.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolate: 'clamp'
}) : 0);
const translateX = progress.interpolate({
inputRange: [0, 1, 2],
outputRange: I18nManager.getConstants().isRTL ? [screen.width, 0, -screen.width] : [-screen.width, 0, screen.width]
});
const transform = [{
translateX
}];
return {
leftButtonStyle: {
transform
},
rightButtonStyle: {
transform
},
titleStyle: {
transform
},
backgroundStyle: {
transform
}
};
}
/**
* Simple translate animation to translate the header to slide up.
*/
export function forSlideUp(_ref5) {
let {
current,
next,
layouts: {
header
}
} = _ref5;
const progress = add(current.progress.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolate: 'clamp'
}), next ? next.progress.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolate: 'clamp'
}) : 0);
const translateY = progress.interpolate({
inputRange: [0, 1, 2],
outputRange: [-header.height, 0, -header.height]
});
const transform = [{
translateY
}];
return {
leftButtonStyle: {
transform
},
rightButtonStyle: {
transform
},
titleStyle: {
transform
},
backgroundStyle: {
transform
}
};
}
export function forNoAnimation() {
return {};
}
//# sourceMappingURL=HeaderStyleInterpolators.js.map