infojune/resources/sass/materialize/js/parallax.js

139 lines
3.9 KiB
JavaScript

(function($) {
'use strict';
let _defaults = {
responsiveThreshold: 0 // breakpoint for swipeable
};
class Parallax extends Component {
constructor(el, options) {
super(Parallax, el, options);
this.el.M_Parallax = this;
/**
* Options for the Parallax
* @member Parallax#options
* @prop {Number} responsiveThreshold
*/
this.options = $.extend({}, Parallax.defaults, options);
this._enabled = window.innerWidth > this.options.responsiveThreshold;
this.$img = this.$el.find('img').first();
this.$img.each(function() {
let el = this;
if (el.complete) $(el).trigger('load');
});
this._updateParallax();
this._setupEventHandlers();
this._setupStyles();
Parallax._parallaxes.push(this);
}
static get defaults() {
return _defaults;
}
static init(els, options) {
return super.init(this, els, options);
}
/**
* Get Instance
*/
static getInstance(el) {
let domElem = !!el.jquery ? el[0] : el;
return domElem.M_Parallax;
}
/**
* Teardown component
*/
destroy() {
Parallax._parallaxes.splice(Parallax._parallaxes.indexOf(this), 1);
this.$img[0].style.transform = '';
this._removeEventHandlers();
this.$el[0].M_Parallax = undefined;
}
static _handleScroll() {
for (let i = 0; i < Parallax._parallaxes.length; i++) {
let parallaxInstance = Parallax._parallaxes[i];
parallaxInstance._updateParallax.call(parallaxInstance);
}
}
static _handleWindowResize() {
for (let i = 0; i < Parallax._parallaxes.length; i++) {
let parallaxInstance = Parallax._parallaxes[i];
parallaxInstance._enabled =
window.innerWidth > parallaxInstance.options.responsiveThreshold;
}
}
_setupEventHandlers() {
this._handleImageLoadBound = this._handleImageLoad.bind(this);
this.$img[0].addEventListener('load', this._handleImageLoadBound);
if (Parallax._parallaxes.length === 0) {
Parallax._handleScrollThrottled = M.throttle(Parallax._handleScroll, 5);
window.addEventListener('scroll', Parallax._handleScrollThrottled);
Parallax._handleWindowResizeThrottled = M.throttle(Parallax._handleWindowResize, 5);
window.addEventListener('resize', Parallax._handleWindowResizeThrottled);
}
}
_removeEventHandlers() {
this.$img[0].removeEventListener('load', this._handleImageLoadBound);
if (Parallax._parallaxes.length === 0) {
window.removeEventListener('scroll', Parallax._handleScrollThrottled);
window.removeEventListener('resize', Parallax._handleWindowResizeThrottled);
}
}
_setupStyles() {
this.$img[0].style.opacity = 1;
}
_handleImageLoad() {
this._updateParallax();
}
_updateParallax() {
let containerHeight = this.$el.height() > 0 ? this.el.parentNode.offsetHeight : 500;
let imgHeight = this.$img[0].offsetHeight;
let parallaxDist = imgHeight - containerHeight;
let bottom = this.$el.offset().top + containerHeight;
let top = this.$el.offset().top;
let scrollTop = M.getDocumentScrollTop();
let windowHeight = window.innerHeight;
let windowBottom = scrollTop + windowHeight;
let percentScrolled = (windowBottom - top) / (containerHeight + windowHeight);
let parallax = parallaxDist * percentScrolled;
if (!this._enabled) {
this.$img[0].style.transform = '';
} else if (bottom > scrollTop && top < scrollTop + windowHeight) {
this.$img[0].style.transform = `translate3D(-50%, ${parallax}px, 0)`;
}
}
}
/**
* @static
* @memberof Parallax
*/
Parallax._parallaxes = [];
M.Parallax = Parallax;
if (M.jQueryLoaded) {
M.initializeJqueryWrapper(Parallax, 'parallax', 'M_Parallax');
}
})(cash);