Skip to content

Commit

Permalink
Added scale to image when scroll to bottom (after exceed headerHeight)
Browse files Browse the repository at this point in the history
  • Loading branch information
kyaroru committed Sep 21, 2017
1 parent 065278e commit 061190c
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 16 deletions.
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@
$ npm i react-native-parallax-header --save
```
## Demo
![iPhone X (Image)](http://g.recordit.co/MpM4nTpzKo.gif)
![iPhone X (Color)](http://g.recordit.co/oTwlJaCPN0.gif)
### iPhone X
![iPhone X (Image)](http://g.recordit.co/o24X5s9rFv.gif)
![iPhone X (Color)](http://g.recordit.co/Owbt2X4ZCo.gif)

### iPhone 8
![iPhone 8 (Image)](http://g.recordit.co/7dbGiEDx7H.gif)
![iPhone 8 (Color)](http://g.recordit.co/YxXtQjTXMU.gif)

## Example
```jsx
Expand All @@ -35,10 +40,12 @@ render() {
<View style={styles.container}>
<ReactNativeParallaxHeader
headerHeight={170}
extraScrollHeight={20}
navbarColor={Colors.primary}
title={'Parallax Header :p'}
titleStyle={styles.titleStyle}
backgroundImage={viewImages.background}
backgroundImageScale={1.2}
renderNavBar={this.renderNavBar}
renderContent={this.renderContent}
/>
Expand All @@ -52,11 +59,13 @@ render() {
| -------- | ---- | -------- | ----------- | ------- |
| `renderNavBar` | `func` | No | This renders the nav bar component | Empty `<View />` |
| `renderContent` | `func` | **YES** | This renders the scroll view content | - |
| `headerHeight` | `number` | No | This is the header maximum height | Default to `200` |
| `backgroundColor` | `string` | No | This is the color of the parallax background (before scrolling up), **will not be used if `backgroundImage` is specified** | Default color is `#303F9F` |
| `backgroundImage` | `image source` | No | This renders the background image of the header | Default is `null` |
| `backgroundImageScale` | `number` | No | This is the image scale (after scrolling to bottom & exceed the headerHeight) | Default is `1.5` |
| `extraScrollHeight` | `number` | No | This is the extra scroll height (after scrolling to bottom & exceed the headerHeight) | Default is `50` |
| `navbarColor` | `string` | No | This is the background color of the navbar (after scroll up) | Default color is `3498db` |
| `title` | `string` | No | This is the title to be display in the header | Default is empty string `‘’` |
| `titleStyle` | `style` | No | This is the title style to override default font size/color | Default to `color: ‘white’ `text and `fontSize: 16` |
| `headerHeight` | `number` | No | This is the header maximum height | Default to `200` |
| `scrollEventThrottle` | `number` | No | This is the scroll event throttle | Default is `16` |

53 changes: 40 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ const NAV_BAR_HEIGHT = Platform.OS === 'ios' ? (IS_IPHONE_X ? 88 : 64) : 45;
const SCROLL_EVENT_THROTTLE = 16;
const DEFAULT_HEADER_MAX_HEIGHT = 200;
const DEFAULT_HEADER_MIN_HEIGHT = NAV_BAR_HEIGHT;
const DEFAULT_EXTRA_SCROLL_HEIGHT = 50;
const DEFAULT_BACKGROUND_IMAGE_SCALE = 1.5;

const DEFAULT_NAVBAR_COLOR = '#3498db';
const DEFAULT_BACKGROUND_COLOR = '#303F9F';
const DEFAULT_TITLE_COLOR = 'white';
Expand Down Expand Up @@ -92,35 +95,53 @@ class RNParallax extends Component {
return headerHeight - DEFAULT_HEADER_MIN_HEIGHT;
}

getExtraScrollHeight() {
const { extraScrollHeight } = this.props;
return extraScrollHeight;
}

getBackgroundImageScale() {
const { backgroundImageScale } = this.props;
return backgroundImageScale;
}

getHeaderHeight() {
const { headerHeight } = this.props;
return this.state.scrollY.interpolate({
inputRange: [0, this.getHeaderScrollDistance()],
outputRange: [headerHeight, DEFAULT_HEADER_MIN_HEIGHT],
inputRange: [-this.getExtraScrollHeight(), 0, this.getHeaderScrollDistance()],
outputRange: [headerHeight + this.getExtraScrollHeight(), headerHeight, DEFAULT_HEADER_MIN_HEIGHT],
extrapolate: 'clamp',
});
}

getImageOpacity() {
return this.state.scrollY.interpolate({
inputRange: [0, this.getHeaderScrollDistance() / 2, this.getHeaderScrollDistance()],
outputRange: [1, 1, 0],
inputRange: [-this.getExtraScrollHeight(), 0, this.getHeaderScrollDistance() / 2, this.getHeaderScrollDistance()],
outputRange: [1, 1, 1, 0],
extrapolate: 'clamp',
});
}

getImageTranslate() {
return this.state.scrollY.interpolate({
inputRange: [0, this.getHeaderScrollDistance()],
outputRange: [0, -50],
inputRange: [-this.getExtraScrollHeight(), 0, this.getHeaderScrollDistance()],
outputRange: [this.getExtraScrollHeight(), 0, -50],
extrapolate: 'clamp',
});
}

getImageScale() {
return this.state.scrollY.interpolate({
inputRange: [-this.getExtraScrollHeight(), 0, this.getHeaderScrollDistance()],
outputRange: [this.getBackgroundImageScale(), 1, 1],
extrapolate: 'clamp'
});
}

getTitleTranslate() {
return this.state.scrollY.interpolate({
inputRange: [0, this.getHeaderScrollDistance() / 2, this.getHeaderScrollDistance()],
outputRange: [0, 0, Platform.OS === 'ios' ? -2 : 0],
inputRange: [-this.getExtraScrollHeight(), 0, this.getHeaderScrollDistance() / 2, this.getHeaderScrollDistance()],
outputRange: [5, 0, 0, Platform.OS === 'ios' ? -2 : 0],
extrapolate: 'clamp',
});
}
Expand Down Expand Up @@ -162,14 +183,15 @@ class RNParallax extends Component {
const { headerHeight, backgroundImage } = this.props;
const imageOpacity = this.getImageOpacity();
const imageTranslate = this.getImageTranslate();
const imageScale = this.getImageScale();

return (
<Animated.Image
style={[
styles.backgroundImage,
{
opacity: imageOpacity,
transform: [{ translateY: imageTranslate }],
transform: [{ translateY: imageTranslate }, { scale: imageScale }],
height: headerHeight,
},
]}
Expand All @@ -182,14 +204,15 @@ class RNParallax extends Component {
const { headerHeight, backgroundColor } = this.props;
const imageOpacity = this.getImageOpacity();
const imageTranslate = this.getImageTranslate();

const imageScale = this.getImageScale();

return (
<Animated.View
style={{
height: headerHeight,
backgroundColor,
opacity: imageOpacity,
transform: [{ translateY: imageTranslate }],
transform: [{ translateY: imageTranslate }, { scale: imageScale }],
}}
/>
);
Expand Down Expand Up @@ -219,7 +242,7 @@ class RNParallax extends Component {
const { renderContent, headerHeight, scrollEventThrottle } = this.props;
return (
<View style={styles.container}>
<ScrollView
<Animated.ScrollView
style={styles.scrollView}
scrollEventThrottle={scrollEventThrottle}
onScroll={Animated.event(
Expand All @@ -229,7 +252,7 @@ class RNParallax extends Component {
<View style={[styles.scrollViewContent, { marginTop: headerHeight }]}>
{renderContent()}
</View>
</ScrollView>
</Animated.ScrollView>
{this.renderHeaderBackground()}
{this.renderHeaderTitle()}
{this.renderHeaderForeground()}
Expand All @@ -248,6 +271,8 @@ RNParallax.propTypes = {
titleStyle: PropTypes.number,
headerHeight: PropTypes.number,
scrollEventThrottle: PropTypes.number,
extraScrollHeight: PropTypes.number,
backgroundImageScale: PropTypes.number,
};

RNParallax.defaultProps = {
Expand All @@ -259,6 +284,8 @@ RNParallax.defaultProps = {
titleStyle: styles.headerText,
headerHeight: DEFAULT_HEADER_MAX_HEIGHT,
scrollEventThrottle: SCROLL_EVENT_THROTTLE,
extraScrollHeight: DEFAULT_EXTRA_SCROLL_HEIGHT,
backgroundImageScale: DEFAULT_BACKGROUND_IMAGE_SCALE,
};

export default RNParallax;

0 comments on commit 061190c

Please sign in to comment.