XylotrechusZ
/**
* ONLY A DEVELOPMENT FRAME TO TEST PERFORMANCE
* ============================================
*
* Currently ununsed
*
* @since 5.0
* @by Kriesi
*/
"use strict";
var avia = window.avia || {};
avia.parallax = function ()
{
//singelton
if(avia.parallax.instance){ return avia.parallax.instance; }
avia.parallax.instance = this;
this.MediaQueryOptions = {
'av-mini-': '(max-width: 479px)',
'av-small-': '(min-width: 480px) and (max-width: 767px)',
'av-medium-': '(min-width: 768px) and (max-width: 989px)'
};
//all parallax elements
this.elements = [];
//run the event binding and therefore initialize parallax movement.
this.bindEvents();
return this;
};
avia.parallax.instance = false;
avia.parallax.prototype = {
//blueprint for a single parallax element
element: function( node , _self )
{
this.dom = node;
this.config = node.dataset;
this.scrollspeed = parseFloat( this.config.parallax_speed || this.config.aviaParallaxRatio || 0 );
this.translate = {x: 0, y: 0, z: 0 };
this.prev = {top:0, left:0};
this.rect = {}; //positioning data of the element
this.css = (styles) => Object.assign(this.dom.style, styles);
this.inViewport = () =>
{
this.rect = this.dom.getBoundingClientRect();
this.translate = this.getTranslateValues();
return (
this.rect.bottom - this.translate.y >= 0 && this.rect.right >= 0 &&
this.rect.top <= (window.innerHeight || document.documentElement.clientHeight) &&
this.rect.left <= (window.innerWidth || document.documentElement.clientWidth)
);
};
this.update = ( force = false ) =>
{
if(! this.scrollspeed ) return;
_self.do( function( el )
{
if( ! el.inViewport() && ! force ) return;
var style = {};
var newLeft = 0;
var offsetTop = window.scrollY + el.rect.top - el.translate.y;
var newTop = (window.scrollY * -1 ) * el.scrollspeed;
if (offsetTop > window.innerHeight )
{
//scroll calc for elements that start out of vieport
//We do this so elements that start out of window do not get re-positioned without a scroll
newTop = parseFloat( (el.rect.top - window.innerHeight - el.translate.y) * el.scrollspeed );
}
console.log(window.innerHeight + el.rect.height);
if(Math.abs(newTop) > window.innerHeight + el.rect.height) return;
if(newTop != el.translate.y)
{
style.transform = "translate3d( "+ newLeft +"px," + newTop + "px, 0px )";
el.css( style );
}
}, this);
};
//https://zellwk.com/blog/css-translate-values-in-javascript/
this.getTranslateValues = () =>
{
const matrix = window.getComputedStyle(this.dom).transform;
if (matrix === 'none' || typeof matrix === 'undefined') return { x: 0, y: 0, z: 0 };
const matrixType = matrix.includes('3d') ? '3d' : '2d';
const matrixValues = matrix.match(/matrix.*\((.+)\)/)[1].split(', ');
if (matrixType === '2d') { return { x: matrixValues[4], y: matrixValues[5], z: 0 }; }
if (matrixType === '3d') { return { x: matrixValues[12], y: matrixValues[13], z: matrixValues[14] }; }
};
//force update el and set visible
this.update();
_self.showElement( () => this.dom.classList.add('active-parallax') );
return this;
},
//end element blueprint
//bind events
bindEvents: function()
{
this.addListener( window , ['scroll'], this.updateElements );
this.addListener( window , ['resize','orientationchange','load','av-height-change'], this.updateElements );
this.addListener( document.body , ['av_resize_finished'], this.updateElements, true);
},
addListener: function( target, events, func, args = false)
{
for (var i = 0, ev; ev = events[i]; i++)
{
target.addEventListener(ev, func.bind( this , args ), { passive: true } );
}
},
//reveal image without jitter
showElement: function( func )
{
if (document.readyState === 'complete') { func() } else { window.addEventListener( "load" , func ) }
},
//add new parallax elements
addElements: function( selector )
{
for (var i = 0, item; item = document.querySelectorAll( selector )[i]; i++)
{
this.elements.push( new this.element( item , this ) );
}
},
//iterate over all elements and run their update script on scroll
updateElements: function(force, e)
{
for (var i = 0, element; element = this.elements[i]; i++)
{
element.update(force);
}
},
//generic wrapper for everything that access or manipulates the DOM
//https://firefox-source-docs.mozilla.org/performance/bestpractices.html
do: function( callback , args , delay = 0)
{
requestAnimationFrame(() => { setTimeout(() => callback.call(this, args) , delay); });
}
};
(function($){
//add ?new-parllax to the url to test. remove in production
if(!window.location.search.includes('new-parallax')) { return; }
var parallax = new avia.parallax();
parallax.addElements('.av-parallax-object');
})(jQuery);