Skip to content

Commit 061190c

Browse files
committed
Added scale to image when scroll to bottom (after exceed headerHeight)
1 parent 065278e commit 061190c

File tree

2 files changed

+52
-16
lines changed

2 files changed

+52
-16
lines changed

README.md

+12-3
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,13 @@
99
$ npm i react-native-parallax-header --save
1010
```
1111
## Demo
12-
![iPhone X (Image)](http://g.recordit.co/MpM4nTpzKo.gif)
13-
![iPhone X (Color)](http://g.recordit.co/oTwlJaCPN0.gif)
12+
### iPhone X
13+
![iPhone X (Image)](http://g.recordit.co/o24X5s9rFv.gif)
14+
![iPhone X (Color)](http://g.recordit.co/Owbt2X4ZCo.gif)
15+
16+
### iPhone 8
17+
![iPhone 8 (Image)](http://g.recordit.co/7dbGiEDx7H.gif)
18+
![iPhone 8 (Color)](http://g.recordit.co/YxXtQjTXMU.gif)
1419

1520
## Example
1621
```jsx
@@ -35,10 +40,12 @@ render() {
3540
<View style={styles.container}>
3641
<ReactNativeParallaxHeader
3742
headerHeight={170}
43+
extraScrollHeight={20}
3844
navbarColor={Colors.primary}
3945
title={'Parallax Header :p'}
4046
titleStyle={styles.titleStyle}
4147
backgroundImage={viewImages.background}
48+
backgroundImageScale={1.2}
4249
renderNavBar={this.renderNavBar}
4350
renderContent={this.renderContent}
4451
/>
@@ -52,11 +59,13 @@ render() {
5259
| -------- | ---- | -------- | ----------- | ------- |
5360
| `renderNavBar` | `func` | No | This renders the nav bar component | Empty `<View />` |
5461
| `renderContent` | `func` | **YES** | This renders the scroll view content | - |
62+
| `headerHeight` | `number` | No | This is the header maximum height | Default to `200` |
5563
| `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` |
5664
| `backgroundImage` | `image source` | No | This renders the background image of the header | Default is `null` |
65+
| `backgroundImageScale` | `number` | No | This is the image scale (after scrolling to bottom & exceed the headerHeight) | Default is `1.5` |
66+
| `extraScrollHeight` | `number` | No | This is the extra scroll height (after scrolling to bottom & exceed the headerHeight) | Default is `50` |
5767
| `navbarColor` | `string` | No | This is the background color of the navbar (after scroll up) | Default color is `3498db` |
5868
| `title` | `string` | No | This is the title to be display in the header | Default is empty string `‘’` |
5969
| `titleStyle` | `style` | No | This is the title style to override default font size/color | Default to `color: ‘white’ `text and `fontSize: 16` |
60-
| `headerHeight` | `number` | No | This is the header maximum height | Default to `200` |
6170
| `scrollEventThrottle` | `number` | No | This is the scroll event throttle | Default is `16` |
6271

index.js

+40-13
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ const NAV_BAR_HEIGHT = Platform.OS === 'ios' ? (IS_IPHONE_X ? 88 : 64) : 45;
2121
const SCROLL_EVENT_THROTTLE = 16;
2222
const DEFAULT_HEADER_MAX_HEIGHT = 200;
2323
const DEFAULT_HEADER_MIN_HEIGHT = NAV_BAR_HEIGHT;
24+
const DEFAULT_EXTRA_SCROLL_HEIGHT = 50;
25+
const DEFAULT_BACKGROUND_IMAGE_SCALE = 1.5;
26+
2427
const DEFAULT_NAVBAR_COLOR = '#3498db';
2528
const DEFAULT_BACKGROUND_COLOR = '#303F9F';
2629
const DEFAULT_TITLE_COLOR = 'white';
@@ -92,35 +95,53 @@ class RNParallax extends Component {
9295
return headerHeight - DEFAULT_HEADER_MIN_HEIGHT;
9396
}
9497

98+
getExtraScrollHeight() {
99+
const { extraScrollHeight } = this.props;
100+
return extraScrollHeight;
101+
}
102+
103+
getBackgroundImageScale() {
104+
const { backgroundImageScale } = this.props;
105+
return backgroundImageScale;
106+
}
107+
95108
getHeaderHeight() {
96109
const { headerHeight } = this.props;
97110
return this.state.scrollY.interpolate({
98-
inputRange: [0, this.getHeaderScrollDistance()],
99-
outputRange: [headerHeight, DEFAULT_HEADER_MIN_HEIGHT],
111+
inputRange: [-this.getExtraScrollHeight(), 0, this.getHeaderScrollDistance()],
112+
outputRange: [headerHeight + this.getExtraScrollHeight(), headerHeight, DEFAULT_HEADER_MIN_HEIGHT],
100113
extrapolate: 'clamp',
101114
});
102115
}
103116

104117
getImageOpacity() {
105118
return this.state.scrollY.interpolate({
106-
inputRange: [0, this.getHeaderScrollDistance() / 2, this.getHeaderScrollDistance()],
107-
outputRange: [1, 1, 0],
119+
inputRange: [-this.getExtraScrollHeight(), 0, this.getHeaderScrollDistance() / 2, this.getHeaderScrollDistance()],
120+
outputRange: [1, 1, 1, 0],
108121
extrapolate: 'clamp',
109122
});
110123
}
111124

112125
getImageTranslate() {
113126
return this.state.scrollY.interpolate({
114-
inputRange: [0, this.getHeaderScrollDistance()],
115-
outputRange: [0, -50],
127+
inputRange: [-this.getExtraScrollHeight(), 0, this.getHeaderScrollDistance()],
128+
outputRange: [this.getExtraScrollHeight(), 0, -50],
116129
extrapolate: 'clamp',
117130
});
118131
}
119132

133+
getImageScale() {
134+
return this.state.scrollY.interpolate({
135+
inputRange: [-this.getExtraScrollHeight(), 0, this.getHeaderScrollDistance()],
136+
outputRange: [this.getBackgroundImageScale(), 1, 1],
137+
extrapolate: 'clamp'
138+
});
139+
}
140+
120141
getTitleTranslate() {
121142
return this.state.scrollY.interpolate({
122-
inputRange: [0, this.getHeaderScrollDistance() / 2, this.getHeaderScrollDistance()],
123-
outputRange: [0, 0, Platform.OS === 'ios' ? -2 : 0],
143+
inputRange: [-this.getExtraScrollHeight(), 0, this.getHeaderScrollDistance() / 2, this.getHeaderScrollDistance()],
144+
outputRange: [5, 0, 0, Platform.OS === 'ios' ? -2 : 0],
124145
extrapolate: 'clamp',
125146
});
126147
}
@@ -162,14 +183,15 @@ class RNParallax extends Component {
162183
const { headerHeight, backgroundImage } = this.props;
163184
const imageOpacity = this.getImageOpacity();
164185
const imageTranslate = this.getImageTranslate();
186+
const imageScale = this.getImageScale();
165187

166188
return (
167189
<Animated.Image
168190
style={[
169191
styles.backgroundImage,
170192
{
171193
opacity: imageOpacity,
172-
transform: [{ translateY: imageTranslate }],
194+
transform: [{ translateY: imageTranslate }, { scale: imageScale }],
173195
height: headerHeight,
174196
},
175197
]}
@@ -182,14 +204,15 @@ class RNParallax extends Component {
182204
const { headerHeight, backgroundColor } = this.props;
183205
const imageOpacity = this.getImageOpacity();
184206
const imageTranslate = this.getImageTranslate();
185-
207+
const imageScale = this.getImageScale();
208+
186209
return (
187210
<Animated.View
188211
style={{
189212
height: headerHeight,
190213
backgroundColor,
191214
opacity: imageOpacity,
192-
transform: [{ translateY: imageTranslate }],
215+
transform: [{ translateY: imageTranslate }, { scale: imageScale }],
193216
}}
194217
/>
195218
);
@@ -219,7 +242,7 @@ class RNParallax extends Component {
219242
const { renderContent, headerHeight, scrollEventThrottle } = this.props;
220243
return (
221244
<View style={styles.container}>
222-
<ScrollView
245+
<Animated.ScrollView
223246
style={styles.scrollView}
224247
scrollEventThrottle={scrollEventThrottle}
225248
onScroll={Animated.event(
@@ -229,7 +252,7 @@ class RNParallax extends Component {
229252
<View style={[styles.scrollViewContent, { marginTop: headerHeight }]}>
230253
{renderContent()}
231254
</View>
232-
</ScrollView>
255+
</Animated.ScrollView>
233256
{this.renderHeaderBackground()}
234257
{this.renderHeaderTitle()}
235258
{this.renderHeaderForeground()}
@@ -248,6 +271,8 @@ RNParallax.propTypes = {
248271
titleStyle: PropTypes.number,
249272
headerHeight: PropTypes.number,
250273
scrollEventThrottle: PropTypes.number,
274+
extraScrollHeight: PropTypes.number,
275+
backgroundImageScale: PropTypes.number,
251276
};
252277

253278
RNParallax.defaultProps = {
@@ -259,6 +284,8 @@ RNParallax.defaultProps = {
259284
titleStyle: styles.headerText,
260285
headerHeight: DEFAULT_HEADER_MAX_HEIGHT,
261286
scrollEventThrottle: SCROLL_EVENT_THROTTLE,
287+
extraScrollHeight: DEFAULT_EXTRA_SCROLL_HEIGHT,
288+
backgroundImageScale: DEFAULT_BACKGROUND_IMAGE_SCALE,
262289
};
263290

264291
export default RNParallax;

0 commit comments

Comments
 (0)