|
6 | 6 | elementsArr,
|
7 | 7 | animationsArr,
|
8 | 8 | scrollTop,
|
9 |
| - windowHeight = $window.height(), |
10 |
| - windowWidth = $window.width(), |
| 9 | + windowHeight, windowWidth, |
| 10 | + documentWidth, documentHeight, |
11 | 11 | scrollTicking = false,
|
12 | 12 | resizeTicking = false,
|
13 | 13 | isTouchDevice = window.Modernizr && typeof(Modernizr.touchevents) != 'undefined' ? Modernizr.touchevents : testTouchEvents();
|
|
20 | 20 | $.fn.parallax = function(method) {
|
21 | 21 | switch (method) {
|
22 | 22 | case 'reset':
|
23 |
| - this.css('transform', ''); |
| 23 | + // todo: implement this |
| 24 | + //this.css('transform', ''); |
24 | 25 | break;
|
25 | 26 | case 'destroy':
|
| 27 | + // todo: implement this |
26 | 28 | $elements.not(this);
|
27 | 29 | break;
|
28 | 30 | default:
|
29 | 31 | if (!isTouchDevice) {
|
30 | 32 | this.data("parallax-js", method);
|
| 33 | + var firstCall = ($elements === null); |
31 | 34 | animationsArr = [];
|
| 35 | + if (firstCall) { |
| 36 | + updateDimensions(); |
| 37 | + } |
32 | 38 | this.each(updateAnimationsArray);
|
33 |
| - if ($elements === null) { |
| 39 | + if (firstCall) { |
34 | 40 | $elements = this;
|
35 | 41 | window.onresize = onResize;
|
36 |
| - window.onscroll = onScroll; |
| 42 | + window.onscroll = onScroll |
37 | 43 | }
|
38 | 44 | else {
|
39 | 45 | $elements.add(this);
|
|
94 | 100 | if (typeof options.scale != "undefined") {
|
95 | 101 | transformOptions.scale = mergeOptions(options.scale, globalOptions);
|
96 | 102 | }
|
| 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 | + } |
97 | 111 | if (typeof options.rotate != "undefined") {
|
98 | 112 | transformOptions.rotate = mergeOptions(options.rotate, globalOptions);
|
99 | 113 | }
|
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) { |
101 | 117 | animation.transform = new TransformContainer($this, transformOptions);
|
102 | 118 | }
|
103 | 119 |
|
| 120 | + if (typeof options.width != "undefined") { |
| 121 | + var widthOptions = mergeOptions(options.width); |
| 122 | + animation.width = new StyleScene($this, widthOptions, 'width'); |
| 123 | + } |
104 | 124 | if (typeof options.opacity != "undefined") {
|
105 | 125 | var opacityOptions = mergeOptions(options.opacity, globalOptions);
|
106 | 126 | animation.opacity = new StyleScene($this, opacityOptions, 'opacity', 1);
|
|
125 | 145 | function onResize() {
|
126 | 146 | if (!resizeTicking) {
|
127 | 147 | window.requestAnimationFrame(function() {
|
128 |
| - windowHeight = $window.height(); |
129 |
| - windowWidth = $window.width(); |
| 148 | + updateDimensions(); |
130 | 149 | $elements.each(updateAnimationsArray);
|
131 | 150 | });
|
132 | 151 | resizeTicking = true;
|
133 | 152 | }
|
134 | 153 | }
|
135 | 154 |
|
| 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 | + |
136 | 168 | function onScroll() {
|
137 | 169 | if (!scrollTicking) {
|
138 | 170 | window.requestAnimationFrame(animateElements);
|
|
202 | 234 | top: offsetTop
|
203 | 235 | };
|
204 | 236 | }
|
205 |
| - |
| 237 | + |
206 | 238 | function convertToOffset(value, axis) {
|
207 | 239 | if (isElement(value)) {
|
208 | 240 | return getOffset(value)[axis === Scene.AXIS_X ? 'left' : 'top'];
|
|
236 | 268 | }
|
237 | 269 | }
|
238 | 270 | }
|
239 |
| - else if (typeof value == "function") { |
| 271 | + else if (typeof value === "function") { |
240 | 272 | value = value(maxValue);
|
241 | 273 | }
|
242 | 274 | return value;
|
|
263 | 295 | this.to = options.to;
|
264 | 296 |
|
265 | 297 | typeof options.trigger != "undefined" || (options.trigger = "100%");
|
| 298 | + console.log(windowHeight); |
266 | 299 | this.trigger = convertOption(options.trigger, options.axis === Scene.AXIS_X ? windowWidth : windowHeight);
|
267 | 300 | this.start = convertToElement(options.start) || options.start;
|
268 | 301 |
|
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); |
290 | 304 | }
|
291 | 305 | Scene.AXIS_X = 'x';
|
292 | 306 | Scene.AXIS_Y = 'y';
|
293 | 307 | Scene.STATE_BEFORE = 'before';
|
294 | 308 | Scene.STATE_DURING = 'during';
|
295 | 309 | Scene.STATE_AFTER = 'after';
|
296 | 310 | 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 | + }, |
297 | 350 | needsUpdate: function() {
|
298 | 351 | this.updateStart();
|
299 | 352 | this.updateDuration();
|
|
314 | 367 | },
|
315 | 368 | updateDuration: function() {
|
316 | 369 | 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); |
319 | 374 | }
|
320 | 375 | },
|
321 | 376 | updateState: function() {
|
|
447 | 502 | }
|
448 | 503 | TransformScene.prototype = $.extend(Object.create(ScalarScene.prototype), {
|
449 | 504 | _getOldValue: function(transform) {
|
450 |
| - return transform.matrix[this.propName](); |
| 505 | + return transform.get(this.propName); |
451 | 506 | },
|
452 | 507 | _setValue: function(newValue, transform) {
|
453 |
| - transform[this.propName] = newValue; |
| 508 | + transform.set(this.propName, newValue); |
454 | 509 | }
|
455 | 510 | });
|
456 | 511 |
|
|
468 | 523 | if (options.scale) {
|
469 | 524 | this.scale = new TransformScene($el, options.scale, 'scale', 1);
|
470 | 525 | }
|
| 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 | + } |
471 | 534 | if (options.rotate) {
|
472 | 535 | this.rotate = new TransformScene($el, options.rotate, 'rotate', 360);
|
473 | 536 | }
|
474 | 537 | }
|
475 | 538 | TransformContainer.prototype = {
|
476 | 539 | update: function(style) {
|
477 |
| - var transform = new Transform(TransformMatrix.fromStyle(style)); |
| 540 | + var matrix = TransformMatrix.fromStyle(style), |
| 541 | + transform = Transform.fromMatrix(matrix); |
478 | 542 | if (this.x && this.x.needsUpdate()) {
|
479 | 543 | this.x.update(transform);
|
480 | 544 | }
|
|
487 | 551 | if (this.scale && this.scale.needsUpdate()) {
|
488 | 552 | this.scale.update(transform);
|
489 | 553 | }
|
| 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 | + } |
490 | 560 | if (this.rotate && this.rotate.needsUpdate()) {
|
491 | 561 | this.rotate.update(transform);
|
492 | 562 | }
|
493 |
| - if (transform.isSet()) { |
| 563 | + if (transform.isChanged()) { |
494 | 564 | var element = this.$el[0],
|
495 | 565 | newValue = transform.toString();
|
496 | 566 | element.style['-webkit-transform'] = newValue;
|
|
628 | 698 | }
|
629 | 699 | };
|
630 | 700 |
|
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; |
633 | 705 | }
|
| 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 | + }; |
634 | 720 | 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; |
641 | 739 | },
|
642 | 740 | 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)'; |
654 | 747 | }
|
655 | 748 | return string;
|
656 | 749 | }
|
|
690 | 783 | var transform = style.transform || style.webkitTransform || style.mozTransform;
|
691 | 784 | return TransformMatrix.fromArray(transform.replace(/^matrix(3d)?\((.*)\)$/, '$2').split(/, /), result);
|
692 | 785 | };
|
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 |
| - }; |
715 | 786 |
|
716 | 787 | if (!isTouchDevice) {
|
717 | 788 | $(function() {
|
|
0 commit comments