Skip to content

Commit 7f19feb

Browse files
committed
added scaleX and scaleY properties
fixed zero duration
1 parent 688ebbc commit 7f19feb

File tree

4 files changed

+153
-81
lines changed

4 files changed

+153
-81
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ translateY
6969

7070
translateZ
7171

72-
#### scale
72+
#### scale or scaleX and scaleY
7373
**Type:** number
7474

7575
#### rotate
@@ -117,6 +117,7 @@ as well as (overridden) for each individually:
117117

118118
Percentage is calculated against element dimensions rather than viewport: "50%" == 0.5 * $(el).outerWidth(true).
119119
For viewport relative values, use viewport units: vh or vw: "100vh" == $(window).height().
120+
Setting duration to "0" will run it till the end of document.
120121

121122
#### trigger
122123
**Type:** number or string (percentage)

examples/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<li><a href="sections.html">Classic parallax sections</a></li>
1010
<li><a href="hero-bg.html">Hero section background image</a></li>
1111
<li><a href="bg.html">Color & background tweening</a></li>
12-
<li><a href="Dave%20Gamache.html">Experiment: recreating Dave Gamache Parallax Demo uing [data-parallax]</a></li>
12+
<li><a href="Dave%20Gamache.html">Experiment: recreating Dave Gamache Parallax Demo using [data-parallax]</a></li>
1313
</ul>
1414
</body>
1515
</html>

jquery.data-parallax.js

Lines changed: 149 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
elementsArr,
77
animationsArr,
88
scrollTop,
9-
windowHeight = $window.height(),
10-
windowWidth = $window.width(),
9+
windowHeight, windowWidth,
10+
documentWidth, documentHeight,
1111
scrollTicking = false,
1212
resizeTicking = false,
1313
isTouchDevice = window.Modernizr && typeof(Modernizr.touchevents) != 'undefined' ? Modernizr.touchevents : testTouchEvents();
@@ -20,20 +20,26 @@
2020
$.fn.parallax = function(method) {
2121
switch (method) {
2222
case 'reset':
23-
this.css('transform', '');
23+
// todo: implement this
24+
//this.css('transform', '');
2425
break;
2526
case 'destroy':
27+
// todo: implement this
2628
$elements.not(this);
2729
break;
2830
default:
2931
if (!isTouchDevice) {
3032
this.data("parallax-js", method);
33+
var firstCall = ($elements === null);
3134
animationsArr = [];
35+
if (firstCall) {
36+
updateDimensions();
37+
}
3238
this.each(updateAnimationsArray);
33-
if ($elements === null) {
39+
if (firstCall) {
3440
$elements = this;
3541
window.onresize = onResize;
36-
window.onscroll = onScroll;
42+
window.onscroll = onScroll
3743
}
3844
else {
3945
$elements.add(this);
@@ -94,13 +100,27 @@
94100
if (typeof options.scale != "undefined") {
95101
transformOptions.scale = mergeOptions(options.scale, globalOptions);
96102
}
103+
else {
104+
if (typeof options.scaleX != "undefined") {
105+
transformOptions.scaleX = mergeOptions(options.scaleX, globalOptions);
106+
}
107+
if (typeof options.scaleY != "undefined") {
108+
transformOptions.scaleY = mergeOptions(options.scaleY, globalOptions);
109+
}
110+
}
97111
if (typeof options.rotate != "undefined") {
98112
transformOptions.rotate = mergeOptions(options.rotate, globalOptions);
99113
}
100-
if (transformOptions.x || transformOptions.y || transformOptions.z || transformOptions.scale || transformOptions.rotate) {
114+
if (transformOptions.x || transformOptions.y || transformOptions.z ||
115+
transformOptions.scale || transformOptions.scaleX || transformOptions.scaleY ||
116+
transformOptions.rotate) {
101117
animation.transform = new TransformContainer($this, transformOptions);
102118
}
103119

120+
if (typeof options.width != "undefined") {
121+
var widthOptions = mergeOptions(options.width);
122+
animation.width = new StyleScene($this, widthOptions, 'width');
123+
}
104124
if (typeof options.opacity != "undefined") {
105125
var opacityOptions = mergeOptions(options.opacity, globalOptions);
106126
animation.opacity = new StyleScene($this, opacityOptions, 'opacity', 1);
@@ -125,14 +145,26 @@
125145
function onResize() {
126146
if (!resizeTicking) {
127147
window.requestAnimationFrame(function() {
128-
windowHeight = $window.height();
129-
windowWidth = $window.width();
148+
updateDimensions();
130149
$elements.each(updateAnimationsArray);
131150
});
132151
resizeTicking = true;
133152
}
134153
}
135154

155+
function updateDimensions() {
156+
var body = document.body,
157+
html = document.documentElement;
158+
159+
windowWidth = Math.max(html.clientWidth, window.innerWidth || 0);
160+
windowHeight = Math.max(html.clientHeight, window.innerHeight || 0);
161+
162+
documentWidth = Math.max( body.scrollWidth, body.offsetWidth,
163+
html.clientWidth, html.scrollWidth, html.offsetWidth );
164+
documentHeight = Math.max( body.scrollHeight, body.offsetHeight,
165+
html.clientHeight, html.scrollHeight, html.offsetHeight );
166+
}
167+
136168
function onScroll() {
137169
if (!scrollTicking) {
138170
window.requestAnimationFrame(animateElements);
@@ -202,7 +234,7 @@
202234
top: offsetTop
203235
};
204236
}
205-
237+
206238
function convertToOffset(value, axis) {
207239
if (isElement(value)) {
208240
return getOffset(value)[axis === Scene.AXIS_X ? 'left' : 'top'];
@@ -236,7 +268,7 @@
236268
}
237269
}
238270
}
239-
else if (typeof value == "function") {
271+
else if (typeof value === "function") {
240272
value = value(maxValue);
241273
}
242274
return value;
@@ -263,37 +295,58 @@
263295
this.to = options.to;
264296

265297
typeof options.trigger != "undefined" || (options.trigger = "100%");
298+
console.log(windowHeight);
266299
this.trigger = convertOption(options.trigger, options.axis === Scene.AXIS_X ? windowWidth : windowHeight);
267300
this.start = convertToElement(options.start) || options.start;
268301

269-
if (typeof options.ease == "function") {
270-
this.ease = options.ease;
271-
}
272-
else {
273-
typeof options.ease == "undefined" || (this.ease = $.easing[options.ease]);
274-
typeof this.ease == "function" || (this.ease = $.easing.linear);
275-
}
276-
277-
if (typeof options.duration != "undefined") {
278-
var maxDuration = options.axis === Scene.AXIS_X ? $el.outerWidth() : $el.outerHeight(),
279-
durationPx = convertOption(options.duration, maxDuration);
280-
this.duration = function() {
281-
return durationPx;
282-
};
283-
}
284-
else {
285-
var scene = this;
286-
this.duration = function() {
287-
return (convertToOffset(scene.$el[0], options.axis) + scene.$el.outerHeight()) - scene.startPx;
288-
};
289-
}
302+
this._setEase(options.ease);
303+
this._setDuration(options.duration);
290304
}
291305
Scene.AXIS_X = 'x';
292306
Scene.AXIS_Y = 'y';
293307
Scene.STATE_BEFORE = 'before';
294308
Scene.STATE_DURING = 'during';
295309
Scene.STATE_AFTER = 'after';
296310
Scene.prototype = {
311+
_setEase: function(ease) {
312+
if (typeof ease == "function") {
313+
this.ease = ease;
314+
}
315+
else {
316+
typeof ease === "undefined" || (this.ease = $.easing[ease]);
317+
typeof this.ease === "function" || (this.ease = $.easing.linear);
318+
}
319+
},
320+
_setDuration: function(duration) {
321+
var validateDurationPx = function(value) {
322+
if (value < 0) {
323+
console.error("Invalid parallax duration: "+value);
324+
}
325+
};
326+
if (typeof duration === "undefined") {
327+
var scene = this;
328+
this.duration = function() {
329+
var durationPx = (convertToOffset(scene.$el[0], scene.axis) + scene.$el.outerHeight()) - scene.startPx;
330+
validateDurationPx(durationPx);
331+
return durationPx;
332+
};
333+
}
334+
else if (typeof duration === "function") {
335+
this.duration = function() {
336+
var durationPx = duration();
337+
validateDurationPx(durationPx);
338+
return durationPx;
339+
};
340+
}
341+
else {
342+
var maxDuration = this.axis === Scene.AXIS_X ? this.$el.outerWidth() : this.$el.outerHeight(),
343+
durationPx = convertOption(duration, maxDuration);
344+
validateDurationPx(durationPx);
345+
this.duration = function () {
346+
return durationPx;
347+
};
348+
}
349+
},
297350
needsUpdate: function() {
298351
this.updateStart();
299352
this.updateDuration();
@@ -314,8 +367,10 @@
314367
},
315368
updateDuration: function() {
316369
this.durationPx = this.duration.call(this);
317-
if (this.durationPx < 0) {
318-
console.error("Invalid parallax duration: "+this.durationPx);
370+
if (this.durationPx === 0) {
371+
this.durationPx = ((this.axis === Scene.AXIS_X ?
372+
documentWidth - windowWidth :
373+
documentHeight - windowHeight) - this.startPx);
319374
}
320375
},
321376
updateState: function() {
@@ -447,10 +502,10 @@
447502
}
448503
TransformScene.prototype = $.extend(Object.create(ScalarScene.prototype), {
449504
_getOldValue: function(transform) {
450-
return transform.matrix[this.propName]();
505+
return transform.get(this.propName);
451506
},
452507
_setValue: function(newValue, transform) {
453-
transform[this.propName] = newValue;
508+
transform.set(this.propName, newValue);
454509
}
455510
});
456511

@@ -468,13 +523,22 @@
468523
if (options.scale) {
469524
this.scale = new TransformScene($el, options.scale, 'scale', 1);
470525
}
526+
else {
527+
if (options.scaleX) {
528+
this.scaleX = new TransformScene($el, options.scaleX, 'scaleX', 1);
529+
}
530+
if (options.scaleY) {
531+
this.scaleY = new TransformScene($el, options.scaleY, 'scaleY', 1);
532+
}
533+
}
471534
if (options.rotate) {
472535
this.rotate = new TransformScene($el, options.rotate, 'rotate', 360);
473536
}
474537
}
475538
TransformContainer.prototype = {
476539
update: function(style) {
477-
var transform = new Transform(TransformMatrix.fromStyle(style));
540+
var matrix = TransformMatrix.fromStyle(style),
541+
transform = Transform.fromMatrix(matrix);
478542
if (this.x && this.x.needsUpdate()) {
479543
this.x.update(transform);
480544
}
@@ -487,10 +551,16 @@
487551
if (this.scale && this.scale.needsUpdate()) {
488552
this.scale.update(transform);
489553
}
554+
if (this.scaleX && this.scaleX.needsUpdate()) {
555+
this.scaleX.update(transform);
556+
}
557+
if (this.scaleY && this.scaleY.needsUpdate()) {
558+
this.scaleY.update(transform);
559+
}
490560
if (this.rotate && this.rotate.needsUpdate()) {
491561
this.rotate.update(transform);
492562
}
493-
if (transform.isSet()) {
563+
if (transform.isChanged()) {
494564
var element = this.$el[0],
495565
newValue = transform.toString();
496566
element.style['-webkit-transform'] = newValue;
@@ -628,29 +698,52 @@
628698
}
629699
};
630700

631-
function Transform(matrix) {
632-
this.matrix = matrix || new TransformMatrix();
701+
function Transform() {
702+
this.translateX = this.translateY = this.translateZ = 0;
703+
this.scaleX = this.scaleY = 1;
704+
this.rotate = 0;
633705
}
706+
Transform.fromMatrix = function(matrix, result) {
707+
result || (result = new Transform());
708+
var a = matrix.matrix[0],
709+
b = matrix.matrix[1],
710+
c = matrix.matrix[4],
711+
d = matrix.matrix[5];
712+
result.translateX = matrix.matrix[12];
713+
result.translateY = matrix.matrix[13];
714+
result.translateZ = matrix.matrix[14];
715+
result.scaleX = Math.sqrt(a*a + b*b);
716+
result.scaleY = Math.sqrt(c*c + d*d);
717+
result.rotate = Math.round(Math.atan2(b, a) * (180/Math.PI));
718+
return result;
719+
};
634720
Transform.prototype = {
635-
isSet: function() {
636-
return (typeof this.translateX != "undefined" ||
637-
typeof this.translateY != "undefined" ||
638-
typeof this.translateZ != "undefined" ||
639-
typeof this.scale != "undefined" ||
640-
typeof this.rotate != "undefined")
721+
get: function(propName) {
722+
if (propName === "scale") {
723+
return this.scaleX;
724+
}
725+
return this[propName];
726+
},
727+
set: function(propName, value) {
728+
if (propName === "scale") {
729+
this.scaleX = value;
730+
this.scaleY = value;
731+
}
732+
else {
733+
this[propName] = value;
734+
}
735+
this._changed = true;
736+
},
737+
isChanged: function() {
738+
return this._changed === true;
641739
},
642740
toString: function() {
643-
var x = (typeof this.translateX != "undefined" ? this.translateX : this.matrix.translateX()).toFixed(2),
644-
y = (typeof this.translateY != "undefined" ? this.translateY : this.matrix.translateY()).toFixed(2),
645-
z = (typeof this.translateZ != "undefined" ? this.translateZ : this.matrix.translateZ()).toFixed(2),
646-
scale = (typeof this.scale != "undefined" ? this.scale : this.matrix.scale()),
647-
rotate = (typeof this.rotate != "undefined" ? this.rotate : this.matrix.rotate()),
648-
string = 'translate3d('+x+'px, '+y+'px, '+z+'px)';
649-
if (scale != 1) {
650-
string += ' scale('+scale+')';
651-
}
652-
if (rotate) {
653-
string += 'rotate('+rotate+'deg)';
741+
var string = 'translate3d('+this.translateX+'px, '+this.translateY+'px, '+this.translateZ+'px)';
742+
if (this.scaleX != 1 || this.scaleY != 1) {
743+
string += ' scale('+this.scaleX+','+this.scaleY+')';
744+
}
745+
if (this.rotate) {
746+
string += 'rotate('+this.rotate+'deg)';
654747
}
655748
return string;
656749
}
@@ -690,28 +783,6 @@
690783
var transform = style.transform || style.webkitTransform || style.mozTransform;
691784
return TransformMatrix.fromArray(transform.replace(/^matrix(3d)?\((.*)\)$/, '$2').split(/, /), result);
692785
};
693-
TransformMatrix.prototype = {
694-
translateX: function() {
695-
return this.matrix[12];
696-
},
697-
translateY: function() {
698-
return this.matrix[13];
699-
},
700-
translateZ: function() {
701-
return this.matrix[14];
702-
},
703-
scale: function() {
704-
var a = this.matrix[0],
705-
b = this.matrix[1],
706-
d = 10;
707-
return Math.round( Math.sqrt( a*a + b*b ) * d ) / d;
708-
},
709-
rotate: function() {
710-
var a = this.matrix[0],
711-
b = this.matrix[1];
712-
return Math.round(Math.atan2(b, a) * (180/Math.PI));
713-
}
714-
};
715786

716787
if (!isTouchDevice) {
717788
$(function() {

0 commit comments

Comments
 (0)