Skip to content

Commit 0af8057

Browse files
committed
bug fixes for pinning, color, left, top
1 parent b20b4ba commit 0af8057

File tree

3 files changed

+78
-38
lines changed

3 files changed

+78
-38
lines changed

README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ All options are **optional**.
148148
**Type:** number or string (percentage or viewport units) or callback function
149149
**Default:** 0
150150

151-
If you need to start the scene after document's beginning or "triggerElement"'s beginning.
151+
If you need to start the scene on an absolute offset or after/before "triggerElement"'s offset.
152152

153153
#### duration
154154
**Type:** number or string (percentage or viewport units) or callback function
@@ -162,8 +162,9 @@ Setting duration to "0" will run it till the end of document.
162162
**Type:** selector
163163
**Default:** the element
164164

165-
If you need another element to act as the trigger.
166-
If you don't need a trigger, set this to "null" or "false".
165+
Use this if you need another element to act as the trigger.
166+
It's not recommended to set this to "null" or "false", because working with absolute offsets can become difficult
167+
when you need to change things.
167168

168169
#### triggerHook
169170
**Type:** number or string (percentage or viewport units) or callback function

jquery.data-parallax.js

+73-34
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
var $elements = null,
55
elementsArr,
66
animationsArr,
7-
scrollTop,
7+
scroll,
88
windowHeight, windowWidth,
99
documentWidth, documentHeight,
1010
scrollTicking = false,
@@ -30,19 +30,20 @@
3030
if (!isTouchDevice) {
3131
this.data("parallax-js", method);
3232
var firstCall = ($elements === null);
33-
animationsArr = [];
3433
if (firstCall) {
3534
updateDimensions();
3635
}
37-
this.each(updateAnimationsArray);
3836
if (firstCall) {
3937
$elements = this;
4038
window.onresize = onResize;
41-
window.onscroll = onScroll
39+
window.onscroll = onScroll;
40+
elementsArr = [];
41+
animationsArr = [];
4242
}
4343
else {
4444
$elements.add(this);
4545
}
46+
updateAnimationsArray.call(this, elementsArr.length);
4647
elementsArr = $elements.toArray();
4748
onScroll();
4849
}
@@ -78,8 +79,22 @@
7879
}
7980
return optionsArr;
8081
}
82+
83+
function rebuildAnimationsArray() {
84+
animationsArr = [];
85+
PinScene.scenes = [];
86+
updateAnimationsArray.call($elements);
87+
}
88+
89+
function updateAnimationsArray(offset) {
90+
typeof offset === "number" || (offset = 0);
91+
this.each(function(i) {
92+
var idx = offset+i;
93+
animationsArr[idx] = createAnimations.call(this);
94+
});
95+
}
8196

82-
function updateAnimationsArray(idx) {
97+
function createAnimations() {
8398
var $this = $(this),
8499
animations = [],
85100
optionsArr = parseOptions.call($this);
@@ -136,11 +151,11 @@
136151

137152
if (typeof options.top != "undefined") {
138153
var topOptions = mergeOptions(options.top, globalOptions);
139-
animation.top = new StyleScene($this, topOptions, 'top');
154+
animation.top = new StyleScene($this, topOptions, 'top', $this.offsetParent().height(), "px");
140155
}
141156
if (typeof options.left != "undefined") {
142157
var leftOptions = mergeOptions(options.left, globalOptions);
143-
animation.left = new StyleScene($this, leftOptions, 'left');
158+
animation.left = new StyleScene($this, leftOptions, 'left', $this.offsetParent().width(), "px");
144159
}
145160
if (typeof options.width != "undefined") {
146161
var widthOptions = mergeOptions(options.width, globalOptions);
@@ -168,14 +183,14 @@
168183
}
169184
animations.push(animation);
170185
}
171-
animationsArr[idx] = animations;
186+
return animations;
172187
}
173188

174189
function onResize() {
175190
if (!resizeTicking) {
176191
window.requestAnimationFrame(function() {
177192
updateDimensions();
178-
$elements.each(updateAnimationsArray);
193+
rebuildAnimationsArray();
179194
});
180195
resizeTicking = true;
181196
}
@@ -202,12 +217,19 @@
202217
}
203218

204219
function animateElements() {
205-
scrollTop = window.scrollY;
220+
scroll = getScroll();
206221
for (var i= 0, len=elementsArr.length; i<len; i++) {
207222
animateElement.call(elementsArr[i], i);
208223
}
209224
scrollTicking = false;
210225
}
226+
227+
function getScroll() {
228+
return {
229+
left: window.pageXOffset || document.documentElement.scrollLeft,
230+
top: window.pageYOffset || document.documentElement.scrollTop
231+
};
232+
}
211233

212234
function animateElement(idx) {
213235
var animations = animationsArr[idx],
@@ -235,7 +257,6 @@
235257
var offsetLeft = elem.offsetLeft,
236258
offsetTop = elem.offsetTop,
237259
lastElem = elem;
238-
239260
while (elem = elem.offsetParent) {
240261
if (elem === document.body) { //from my observation, document.body always has scrollLeft/scrollTop == 0
241262
break;
@@ -244,18 +265,18 @@
244265
offsetTop += elem.offsetTop;
245266
lastElem = elem;
246267
}
247-
if (lastElem && lastElem.style.position === 'fixed') { //slow - http://jsperf.com/offset-vs-getboundingclientrect/6
248-
offsetLeft += window.pageXOffset || document.documentElement.scrollLeft;
249-
offsetTop += window.pageYOffset || document.documentElement.scrollTop;
268+
if (lastElem.style.position === 'fixed') { //slow - http://jsperf.com/offset-vs-getboundingclientrect/6
269+
offsetLeft += scroll.left;
270+
offsetTop += scroll.top;
250271
}
251272
return {
252273
left: offsetLeft,
253274
top: offsetTop
254275
};
255276
}
256277

257-
function convertToOffset(value, axis) {
258-
return getOffset(value)[axis === Scene.AXIS_X ? 'left' : 'top'];
278+
function convertToOffset(elem, axis) {
279+
return getOffset(elem)[axis === Scene.AXIS_X ? 'left' : 'top'];
259280
}
260281

261282
function convertToElement(value) {
@@ -364,7 +385,7 @@
364385
if (typeof duration === "undefined") {
365386
var scene = this;
366387
this.duration = function() {
367-
var durationPx = (convertToOffset(scene.$el[0], scene.axis) + scene.$el.outerHeight()) - scene.start;
388+
var durationPx = (convertToOffset(scene.$el[0], scene.axis) + scene.$el.outerHeight(true)) - scene.start;
368389
validateDurationPx(durationPx);
369390
return durationPx;
370391
};
@@ -413,10 +434,10 @@
413434
},
414435
updateState: function() {
415436
this.prevState = this.state;
416-
if (scrollTop < this.start) {
437+
if (scroll.top < this.start) {
417438
this.state = Scene.STATE_BEFORE;
418439
}
419-
else if (scrollTop <= (this.start + this.durationPx)) {
440+
else if (scroll.top <= (this.start + this.durationPx)) {
420441
this.state = Scene.STATE_DURING;
421442
}
422443
else {
@@ -426,7 +447,10 @@
426447
getOffset: function() {
427448
var offset = this.offset;
428449
if (isElement(this.triggerElement)) {
429-
offset += convertToOffset(this.triggerElement, this.axis);
450+
var pinScene = PinScene.findByElement(this.triggerElement);
451+
offset += (pinScene && pinScene.state === Scene.STATE_DURING ?
452+
pinScene.start :
453+
convertToOffset(this.triggerElement, this.axis));
430454
}
431455
return offset;
432456
},
@@ -435,7 +459,7 @@
435459
return 0;
436460
}
437461
else if (this.state === Scene.STATE_DURING) {
438-
var posPx = scrollTop - this.start,
462+
var posPx = scroll.top - this.start,
439463
percent = posPx / this.durationPx,
440464
progress = this.ease.call(this, percent);
441465
return progress;
@@ -453,12 +477,13 @@
453477
}
454478
};
455479

456-
function ScalarScene($el, options, maxValue) {
480+
function ScalarScene($el, options, maxValue, defaultUnit) {
457481
if (typeof maxValue != "undefined") {
458482
options.from = convertOption(options.from, maxValue);
459483
options.to = convertOption(options.to, maxValue);
460484
}
461485
Scene.call(this, $el, options);
486+
this.unit = typeof this.to === "string" ? parseUnit(this.to) : defaultUnit;
462487
}
463488
ScalarScene.prototype = inherit(Scene.prototype, {
464489
_getNewValue: function() {
@@ -468,17 +493,17 @@
468493
}
469494
if (typeof this.to === "string") {
470495
var from = parseFloat(this.from),
471-
to = parseFloat(this.to),
472-
suffix = parseUnit(this.to);
473-
return interpolate(from, to, this.getProgress()) + suffix;
496+
to = parseFloat(this.to);
497+
return interpolate(from, to, this.getProgress()) + this.unit;
474498
}
475-
return interpolate(this.from, this.to, this.getProgress());
499+
var suffix = (typeof this.unit === "undefined" ? 0 : this.unit)
500+
return interpolate(this.from, this.to, this.getProgress()) + suffix;
476501
}
477502
});
478503

479-
function StyleScene($el, options, styleName, maxValue) {
504+
function StyleScene($el, options, styleName, maxValue, defaultUnit) {
480505
this.styleName = styleName;
481-
ScalarScene.call(this, $el, options, maxValue);
506+
ScalarScene.call(this, $el, options, maxValue, defaultUnit);
482507
}
483508
StyleScene.prototype = inherit(ScalarScene.prototype, {
484509
_getOldValue: function(style) {
@@ -509,7 +534,17 @@
509534
isElement(options.to) || (options.to = $el[0]);
510535
typeof options.triggerHook != "undefined" || (options.triggerHook = 0);
511536
Scene.call(this, $el, options);
537+
PinScene.scenes.push(this);
512538
}
539+
PinScene.scenes = [];
540+
PinScene.findByElement = function(elem) {
541+
var scenes = PinScene.scenes;
542+
for (var i=0, len=scenes.length; i<len; i++) {
543+
if (scenes[i].$el[0] === elem) {
544+
return scenes[i];
545+
}
546+
}
547+
};
513548
PinScene.prototype = inherit(Scene.prototype, {
514549
updateStart: function() {
515550
if (this.state != Scene.STATE_DURING) {
@@ -525,23 +560,27 @@
525560
return {
526561
position: toStyle.position,
527562
top: toStyle.top,
528-
left: toStyle.left
563+
left: toStyle.left,
564+
marginLeft: "",
565+
marginTop: ""
529566
};
530567
},
531568
_getNewValue: function() {
532569
if (this.state == Scene.STATE_DURING) {
533570
return {
534571
position: 'fixed',
535572
top: this.from.pinTop + 'px',
536-
left: this.from.pinLeft + 'px'
573+
left: this.from.pinLeft + 'px',
574+
marginLeft: 0,
575+
marginTop: 0
537576
};
538577
}
539578
return this.from;
540579
},
541580
_setValue: function(newValue) {
542-
this.to.style.position = newValue.position;
543-
this.to.style.top = newValue.top;
544-
this.to.style.left = newValue.left;
581+
for (var styleName in newValue) {
582+
this.to.style[styleName] = newValue[styleName];
583+
}
545584
},
546585
_setFrom: function(defaultValue) {
547586
if (typeof this.from === "undefined") {
@@ -705,7 +744,7 @@
705744
parseInt(string.substr(5,2),16)
706745
], result);
707746
}
708-
return RGBColor.fromArray(string.replace(/^rgb(a)?\((.*)\)$/, '$2').split(/, /), result);
747+
return RGBColor.fromArray(string.replace(/^rgb(a)?\((.*)\)$/, '$2').split(","), result);
709748
};
710749
RGBColor.fromHSV = function(hsv, result) {
711750
result || (result = new RGBColor());

0 commit comments

Comments
 (0)