Skip to content

Commit d1ecd6b

Browse files
authored
Merge branch 'master' into master
2 parents 68069ad + 22fa922 commit d1ecd6b

File tree

3 files changed

+65
-37
lines changed

3 files changed

+65
-37
lines changed

README.md

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,39 @@ Simple parallax scrolling effect inspired by [Spotify.com](http://spotify.com/)
66

77
## Installation
88

9-
Download package or install with Bower and include `parallax.min.js` in your document after including jQuery.
9+
### NPM
1010

1111
```bash
12-
$ bower i --save parallax.js
12+
npm i --save jquery-parallax.js
13+
```
14+
15+
### Yarn
16+
17+
```bash
18+
yarn add jquery-parallax.js
1319
```
1420

15-
Or install with NPM
21+
### Bower
22+
23+
Please note that although Bower is still maintained, they recommend Yarn for new projects.
1624

1725
```bash
18-
$ npm i --save jquery-parallax.js
26+
$ bower i --save parallax.js
1927
```
2028

29+
### Setup
30+
31+
Include `parallax.min.js` in your document after including jQuery.
32+
2133
```html
22-
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
34+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
2335
<script src="/path/to/parallax.min.js"></script>
2436
```
2537

2638
## Usage
2739

40+
Please note, that `<!DOCTYPE html>` on top of your document is required!
41+
2842
### Via data attributes
2943

3044
To easily add a parallax effect behind an element, add `data-parallax="scroll"` to the element you want to use, and specify an image with `data-image-src="/path/to/image.jpg"`.
@@ -43,7 +57,7 @@ $('.parallax-window').parallax({imageSrc: '/path/to/image.jpg'});
4357

4458
### Notes
4559

46-
What parallax.js will do is create a fixed-position element for each parallax image at the start of the document's body. This mirror element will sit behind the other elements and match the position and dimensions of its target object.
60+
What parallax.js will do is create a fixed-position element for each parallax image at the start of the document's body (or another configurable container). This mirror element will sit behind the other elements and match the position and dimensions of its target object.
4761

4862
Due to the nature of this implementation, you must ensure that these parallax objects and any layers below them are transparent so that you can see the parallax effect underneath. Also, if there is no other content in this element, you will need to ensure that it has some fixed dimensions otherwise you won't see anything.
4963

@@ -178,6 +192,12 @@ Note that when specifying these options as html data-attributes, you should conv
178192
<td>false</td>
179193
<td>(Experimental) If true, will freeze the parallax effect when "over scrolling" in browsers like Safari to prevent unexpected gaps caused by negative scroll positions.</td>
180194
</tr>
195+
<tr>
196+
<td>mirrorContainer</td>
197+
<td>jQuery Selector</td>
198+
<td>body</td>
199+
<td>The parallax mirror will be prepended into this container.</td>
200+
</tr>
181201
</tbody>
182202
</table>
183203

parallax.js

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
var vendors = ['ms', 'moz', 'webkit', 'o'];
1515
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
1616
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
17-
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
18-
|| window[vendors[x]+'CancelRequestAnimationFrame'];
17+
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
1918
}
2019

2120
if (!window.requestAnimationFrame)
@@ -65,8 +64,8 @@
6564
positions = [positions[1], positions[0]];
6665
}
6766

68-
if (this.positionX != undefined) positions[0] = this.positionX.toLowerCase();
69-
if (this.positionY != undefined) positions[1] = this.positionY.toLowerCase();
67+
if (this.positionX !== undefined) positions[0] = this.positionX.toLowerCase();
68+
if (this.positionY !== undefined) positions[1] = this.positionY.toLowerCase();
7069

7170
self.positionX = positions[0];
7271
self.positionY = positions[1];
@@ -113,7 +112,7 @@
113112
return this;
114113
}
115114

116-
this.$mirror = $('<div />').prependTo('body');
115+
this.$mirror = $('<div />').prependTo(this.mirrorContainer);
117116

118117
var slider = this.$element.find('>.parallax-slider');
119118
var sliderExisted = false;
@@ -154,7 +153,7 @@
154153
this.$slider.trigger('load');
155154
}
156155

157-
};
156+
}
158157

159158

160159
// Parallax Instance Methods
@@ -167,6 +166,7 @@
167166
androidFix: true,
168167
position: 'center',
169168
overScrollFix: false,
169+
mirrorContainer: 'body',
170170

171171
refresh: function() {
172172
this.boxWidth = this.$element.outerWidth();
@@ -181,13 +181,14 @@
181181
var minOffset = Math.max(this.boxOffsetTop + this.boxHeight - winHeight, 0);
182182
var imageHeightMin = this.boxHeight + (maxOffset - minOffset) * (1 - this.speed) | 0;
183183
var imageOffsetMin = (this.boxOffsetTop - maxOffset) * (1 - this.speed) | 0;
184+
var margin;
184185

185186
if (imageHeightMin * this.aspectRatio >= this.boxWidth) {
186187
this.imageWidth = imageHeightMin * this.aspectRatio | 0;
187188
this.imageHeight = imageHeightMin;
188189
this.offsetBaseTop = imageOffsetMin;
189190

190-
var margin = this.imageWidth - this.boxWidth;
191+
margin = this.imageWidth - this.boxWidth;
191192

192193
if (this.positionX == 'left') {
193194
this.offsetLeft = 0;
@@ -203,7 +204,7 @@
203204
this.imageHeight = this.boxWidth / this.aspectRatio | 0;
204205
this.offsetLeft = 0;
205206

206-
var margin = this.imageHeight - imageHeightMin;
207+
margin = this.imageHeight - imageHeightMin;
207208

208209
if (this.positionY == 'top') {
209210
this.offsetBaseTop = imageOffsetMin;
@@ -233,19 +234,15 @@
233234
}
234235

235236
this.$mirror.css({
236-
transform: 'translate3d(0px, 0px, 0px)',
237+
transform: 'translate3d('+this.mirrorLeft+'px, '+(this.mirrorTop - overScroll)+'px, 0px)',
237238
visibility: this.visibility,
238-
top: this.mirrorTop - overScroll,
239-
left: this.mirrorLeft,
240239
height: this.boxHeight,
241240
width: this.boxWidth
242241
});
243242

244243
this.$slider.css({
245-
transform: 'translate3d(0px, 0px, 0px)',
244+
transform: 'translate3d('+this.offsetLeft+'px, '+this.offsetTop+'px, 0px)',
246245
position: 'absolute',
247-
top: this.offsetTop,
248-
left: this.offsetLeft,
249246
height: this.imageHeight,
250247
width: this.imageWidth,
251248
maxWidth: 'none'
@@ -271,6 +268,8 @@
271268
setup: function() {
272269
if (this.isReady) return;
273270

271+
var self = this;
272+
274273
var $doc = $(document), $win = $(window);
275274

276275
var loadDimensions = function() {
@@ -291,6 +290,7 @@
291290

292291
$win.on('resize.px.parallax load.px.parallax', function() {
293292
loadDimensions();
293+
self.refresh();
294294
Parallax.isFresh = false;
295295
Parallax.requestRender();
296296
})
@@ -303,6 +303,20 @@
303303
loadScrollPosition();
304304

305305
this.isReady = true;
306+
307+
var lastPosition = -1;
308+
309+
function frameLoop() {
310+
if (lastPosition == window.pageYOffset) { // Avoid overcalculations
311+
window.requestAnimationFrame(frameLoop);
312+
return false;
313+
} else lastPosition = window.pageYOffset;
314+
315+
self.render();
316+
window.requestAnimationFrame(frameLoop);
317+
}
318+
319+
frameLoop();
306320
},
307321

308322
configure: function(options) {
@@ -314,25 +328,19 @@
314328
},
315329

316330
refresh: function() {
317-
$.each(this.sliders, function(){ this.refresh() });
331+
$.each(this.sliders, function(){ this.refresh(); });
318332
this.isFresh = true;
319333
},
320334

321335
render: function() {
322336
this.isFresh || this.refresh();
323-
$.each(this.sliders, function(){ this.render() });
337+
$.each(this.sliders, function(){ this.render(); });
324338
},
325339

326340
requestRender: function() {
327341
var self = this;
328-
329-
if (!this.isBusy) {
330-
this.isBusy = true;
331-
window.requestAnimationFrame(function() {
332-
self.render();
333-
self.isBusy = false;
334-
});
335-
}
342+
self.render();
343+
self.isBusy = false;
336344
},
337345
destroy: function(el){
338346
var i,
@@ -373,13 +381,13 @@
373381
}
374382
if (typeof option == 'string') {
375383
if(option == 'destroy'){
376-
Parallax['destroy'](this);
384+
Parallax.destroy(this);
377385
}else{
378386
Parallax[option]();
379387
}
380388
}
381-
})
382-
};
389+
});
390+
}
383391

384392
var old = $.fn.parallax;
385393

@@ -397,8 +405,8 @@
397405

398406
// Parallax Data-API
399407

400-
$(document).on('ready.px.parallax.data-api', function () {
401-
$('[data-parallax="scroll"]').parallax();
408+
$( function () {
409+
$('[data-parallax="scroll"]').parallax();
402410
});
403411

404412
}(jQuery, window, document));

0 commit comments

Comments
 (0)