/*! * parallax.js v1.5.0 (http://pixelcog.github.io/parallax.js/) * @copyright 2016 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.imagesrc && 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.imagesrc && this.androidfix && !this.$element.is('img')) { this.$element.css({ backgroundimage: 'url(' + this.imagesrc + ')', backgroundsize: 'cover', backgroundposition: this.position }); } return this; } this.$mirror = $('
').prependto(this.mirrorcontainer); var slider = this.$element.find('>.parallax-slider'); var sliderexisted = false; if (slider.length == 0) this.$slider = $('').prependto(this.$mirror); else { this.$slider = slider.prependto(this.$mirror) sliderexisted = true; } 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(); }); if (!sliderexisted) this.$slider[0].src = this.imagesrc; if (this.naturalheight && this.naturalwidth || this.$slider[0].complete || slider.length > 0) { this.$slider.trigger('load'); } } // parallax instance methods $.extend(parallax.prototype, { speed: 0.2, bleed: 0, zindex: -100, iosfix: false, androidfix: false, position: 'center', overscrollfix: false, mirrorcontainer: 'body', 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; var margin; if (imageheightmin * this.aspectratio >= this.boxwidth) { this.imagewidth = imageheightmin * this.aspectratio | 0; this.imageheight = imageheightmin; this.offsetbasetop = imageoffsetmin; 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; 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'; this.mirrortop = this.boxoffsettop - scrolltop; this.mirrorleft = this.boxoffsetleft - scrollleft; this.offsettop = this.offsetbasetop - this.mirrortop * (1 - this.speed); } else { this.visibility = 'hidden'; } this.$mirror.css({ transform: 'translate3d('+this.mirrorleft+'px, '+(this.mirrortop - overscroll)+'px, 0px)', visibility: this.visibility, height: this.boxheight, width: this.boxwidth }); this.$slider.css({ transform: 'translate3d('+this.offsetleft+'px, '+this.offsettop+'px, 0px)', position: 'absolute', 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 self = this; var $doc = $(document), $win = $(window); var loaddimensions = function() { parallax.winheight = $win.height(); parallax.winwidth = $win.width(); parallax.docheight = $doc.height(); parallax.docwidth = $doc.width(); }; var loadscrollposition = function() { var winscrolltop = $win.scrolltop(); var scrolltopmax = parallax.docheight - parallax.winheight; var scrollleftmax = parallax.docwidth - parallax.winwidth; parallax.scrolltop = math.max(0, math.min(scrolltopmax, winscrolltop)); parallax.scrollleft = math.max(0, math.min(scrollleftmax, $win.scrollleft())); parallax.overscroll = math.max(winscrolltop - scrolltopmax, math.min(winscrolltop, 0)); }; $win.on('resize.px.parallax load.px.parallax', function() { loaddimensions(); self.refresh(); parallax.isfresh = false; parallax.requestrender(); }) .on('scroll.px.parallax load.px.parallax', function() { loadscrollposition(); parallax.requestrender(); }); loaddimensions(); loadscrollposition(); this.isready = true; var lastposition = -1; function frameloop() { if (lastposition == window.pageyoffset) { // avoid overcalculations window.requestanimationframe(frameloop); return false; } else lastposition = window.pageyoffset; self.render(); window.requestanimationframe(frameloop); } frameloop(); }, 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; self.render(); self.isbusy = false; }, destroy: function(el){ var i, parallaxelement = $(el).data('px.parallax'); parallaxelement.$mirror.remove(); for(i=0; i < this.sliders.length; i+=1){ if(this.sliders[i] == parallaxelement){ this.sliders.splice(i, 1); } } $(el).data('px.parallax', false); if(this.sliders.length === 0){ $(window).off('scroll.px.parallax resize.px.parallax load.px.parallax'); this.isready = false; parallax.issetup = 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)); } else if (typeof option == 'object') { $.extend($this.data('px.parallax'), options); } if (typeof option == 'string') { if(option == 'destroy'){ parallax.destroy(this); }else{ 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 $( function () { $('[data-parallax="scroll"]').parallax(); }); }(jquery, window, document));