Template:Paris Bettencourt/parallax
/*!
* parallax.js v1.3.1 (http://pixelcog.github.io/parallax.js/) * @copyright 2015 PixelCog, Inc. * @license MIT (https://github.com/pixelcog/parallax.js/blob/master/LICENSE) */
- (function ( $, window, document, undefined ) {
// Polyfill for requestAnimationFrame // via: https://gist.github.com/paulirish/1579671
(function() { var lastTime = 0; var vendors = ['ms', 'moz', 'webkit', 'o']; for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; }
if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16 - (currTime - lastTime)); var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; };
if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) { clearTimeout(id); }; }());
// Parallax Constructor
function Parallax(element, options) { var self = this;
if (typeof options == 'object') { delete options.refresh; delete options.render; $.extend(this, options); }
this.$element = $(element);
if (!this.imageSrc && this.$element.is('img')) { this.imageSrc = this.$element.attr('src'); }
var positions = (this.position + ).toLowerCase().match(/\S+/g) || [];
if (positions.length < 1) { positions.push('center'); } if (positions.length == 1) { positions.push(positions[0]); }
if (positions[0] == 'top' || positions[0] == 'bottom' || positions[1] == 'left' || positions[1] == 'right') { positions = [positions[1], positions[0]]; }
if (this.positionX != undefined) positions[0] = this.positionX.toLowerCase(); if (this.positionY != undefined) positions[1] = this.positionY.toLowerCase();
self.positionX = positions[0]; self.positionY = positions[1];
if (this.positionX != 'left' && this.positionX != 'right') { if (isNaN(parseInt(this.positionX))) { this.positionX = 'center'; } else { this.positionX = parseInt(this.positionX); } }
if (this.positionY != 'top' && this.positionY != 'bottom') { if (isNaN(parseInt(this.positionY))) { this.positionY = 'center'; } else { this.positionY = parseInt(this.positionY); } }
this.position = this.positionX + (isNaN(this.positionX)? : 'px') + ' ' + this.positionY + (isNaN(this.positionY)? : 'px');
if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) { if (this.iosFix && !this.$element.is('img')) { this.$element.css({ backgroundImage: 'url(' + this.imageSrc + ')', backgroundSize: 'cover', backgroundPosition: this.position }); } return this; }
if (navigator.userAgent.match(/(Android)/)) { if (this.androidFix && !this.$element.is('img')) { this.$element.css({ backgroundImage: 'url(' + this.imageSrc + ')', backgroundSize: 'cover', backgroundPosition: this.position }); } return this; }
this.$mirror = $('<div />').prependTo('body'); this.$slider = $('<img />').prependTo(this.$mirror);
this.$mirror.addClass('parallax-mirror').css({ visibility: 'hidden', zIndex: this.zIndex, position: 'fixed', top: 0, left: 0, overflow: 'hidden' });
this.$slider.addClass('parallax-slider').one('load', function() { if (!self.naturalHeight || !self.naturalWidth) { self.naturalHeight = this.naturalHeight || this.height || 1; self.naturalWidth = this.naturalWidth || this.width || 1; } self.aspectRatio = self.naturalWidth / self.naturalHeight;
Parallax.isSetup || Parallax.setup(); Parallax.sliders.push(self); Parallax.isFresh = false; Parallax.requestRender(); });
this.$slider[0].src = this.imageSrc;
if (this.naturalHeight && this.naturalWidth || this.$slider[0].complete) { this.$slider.trigger('load'); }
};
// Parallax Instance Methods
$.extend(Parallax.prototype, { speed: 0.2, bleed: 0, zIndex: -100, iosFix: true, androidFix: true, position: 'center', overScrollFix: false,
refresh: function() { this.boxWidth = this.$element.outerWidth(); this.boxHeight = this.$element.outerHeight() + this.bleed * 2; this.boxOffsetTop = this.$element.offset().top - this.bleed; this.boxOffsetLeft = this.$element.offset().left; this.boxOffsetBottom = this.boxOffsetTop + this.boxHeight;
var winHeight = Parallax.winHeight; var docHeight = Parallax.docHeight; var maxOffset = Math.min(this.boxOffsetTop, docHeight - winHeight); var minOffset = Math.max(this.boxOffsetTop + this.boxHeight - winHeight, 0); var imageHeightMin = this.boxHeight + (maxOffset - minOffset) * (1 - this.speed) | 0; var imageOffsetMin = (this.boxOffsetTop - maxOffset) * (1 - this.speed) | 0;
if (imageHeightMin * this.aspectRatio >= this.boxWidth) { this.imageWidth = imageHeightMin * this.aspectRatio | 0; this.imageHeight = imageHeightMin; this.offsetBaseTop = imageOffsetMin;
var margin = this.imageWidth - this.boxWidth;
if (this.positionX == 'left') { this.offsetLeft = 0; } else if (this.positionX == 'right') { this.offsetLeft = - margin; } else if (!isNaN(this.positionX)) { this.offsetLeft = Math.max(this.positionX, - margin); } else { this.offsetLeft = - margin / 2 | 0; } } else { this.imageWidth = this.boxWidth; this.imageHeight = this.boxWidth / this.aspectRatio | 0; this.offsetLeft = 0;
var margin = this.imageHeight - imageHeightMin;
if (this.positionY == 'top') { this.offsetBaseTop = imageOffsetMin; } else if (this.positionY == 'bottom') { this.offsetBaseTop = imageOffsetMin - margin; } else if (!isNaN(this.positionY)) { this.offsetBaseTop = imageOffsetMin + Math.max(this.positionY, - margin); } else { this.offsetBaseTop = imageOffsetMin - margin / 2 | 0; } } },
render: function() { var scrollTop = Parallax.scrollTop; var scrollLeft = Parallax.scrollLeft; var overScroll = this.overScrollFix ? Parallax.overScroll : 0; var scrollBottom = scrollTop + Parallax.winHeight;
if (this.boxOffsetBottom > scrollTop && this.boxOffsetTop < scrollBottom) { this.visibility = 'visible'; } else { this.visibility = 'hidden'; } this.mirrorTop = this.boxOffsetTop - scrollTop; this.mirrorLeft = this.boxOffsetLeft - scrollLeft; this.offsetTop = this.offsetBaseTop - this.mirrorTop * (1 - this.speed);
this.$mirror.css({ transform: 'translate3d(0px, 0px, 0px)', visibility: this.visibility, top: this.mirrorTop - overScroll, left: this.mirrorLeft, height: this.boxHeight, width: this.boxWidth });
this.$slider.css({ transform: 'translate3d(0px, 0px, 0px)', position: 'absolute', top: this.offsetTop, left: this.offsetLeft, height: this.imageHeight, width: this.imageWidth, maxWidth: 'none' }); } });
// Parallax Static Methods
$.extend(Parallax, { scrollTop: 0, scrollLeft: 0, winHeight: 0, winWidth: 0, docHeight: 1 << 30, docWidth: 1 << 30, sliders: [], isReady: false, isFresh: false, isBusy: false,
setup: function() { if (this.isReady) return;
var $doc = $(document), $win = $(window);
$win.on('scroll.px.parallax load.px.parallax', function() { var scrollTopMax = Parallax.docHeight - Parallax.winHeight; var scrollLeftMax = Parallax.docWidth - Parallax.winWidth; Parallax.scrollTop = Math.max(0, Math.min(scrollTopMax, $win.scrollTop())); Parallax.scrollLeft = Math.max(0, Math.min(scrollLeftMax, $win.scrollLeft())); Parallax.overScroll = Math.max($win.scrollTop() - scrollTopMax, Math.min($win.scrollTop(), 0)); Parallax.requestRender(); }) .on('resize.px.parallax load.px.parallax', function() { Parallax.winHeight = $win.height(); Parallax.winWidth = $win.width(); Parallax.docHeight = $doc.height(); Parallax.docWidth = $doc.width(); Parallax.isFresh = false; Parallax.requestRender(); });
this.isReady = true; },
configure: function(options) { if (typeof options == 'object') { delete options.refresh; delete options.render; $.extend(this.prototype, options); } },
refresh: function() { $.each(this.sliders, function(){ this.refresh() }); this.isFresh = true; },
render: function() { this.isFresh || this.refresh(); $.each(this.sliders, function(){ this.render() }); },
requestRender: function() { var self = this;
if (!this.isBusy) { this.isBusy = true; window.requestAnimationFrame(function() { self.render(); self.isBusy = false; }); } } });
// Parallax Plugin Definition
function Plugin(option) { return this.each(function () { var $this = $(this); var options = typeof option == 'object' && option;
if (this == window || this == document || $this.is('body')) { Parallax.configure(options); } else if (!$this.data('px.parallax')) { options = $.extend({}, $this.data(), options); $this.data('px.parallax', new Parallax(this, options)); } if (typeof option == 'string') { Parallax[option](); } }) };
var old = $.fn.parallax;
$.fn.parallax = Plugin; $.fn.parallax.Constructor = Parallax;
// Parallax No Conflict
$.fn.parallax.noConflict = function () { $.fn.parallax = old; return this; };
// Parallax Data-API
$(document).on('ready.px.parallax.data-api', function () { $('[data-parallax="scroll"]').parallax(); });
}(jQuery, window, document));