139 lines
3.9 KiB
JavaScript
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);
|