diff --git a/README.md b/README.md index 4b081fa..c9d53f6 100644 --- a/README.md +++ b/README.md @@ -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 @@ -35,10 +40,12 @@ render() { @@ -52,11 +59,13 @@ render() { | -------- | ---- | -------- | ----------- | ------- | | `renderNavBar` | `func` | No | This renders the nav bar component | Empty `` | | `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` | diff --git a/index.js b/index.js index 197ae4e..f268278 100644 --- a/index.js +++ b/index.js @@ -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'; @@ -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', }); } @@ -162,6 +183,7 @@ class RNParallax extends Component { const { headerHeight, backgroundImage } = this.props; const imageOpacity = this.getImageOpacity(); const imageTranslate = this.getImageTranslate(); + const imageScale = this.getImageScale(); return ( ); @@ -219,7 +242,7 @@ class RNParallax extends Component { const { renderContent, headerHeight, scrollEventThrottle } = this.props; return ( - {renderContent()} - + {this.renderHeaderBackground()} {this.renderHeaderTitle()} {this.renderHeaderForeground()} @@ -248,6 +271,8 @@ RNParallax.propTypes = { titleStyle: PropTypes.number, headerHeight: PropTypes.number, scrollEventThrottle: PropTypes.number, + extraScrollHeight: PropTypes.number, + backgroundImageScale: PropTypes.number, }; RNParallax.defaultProps = { @@ -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;