penguin/AstroJS

Javascript framework for my blog

botanjs/src/Astro/Mechanism/Parallax.js

raw ยท 2965 bytes

(function(){
	var ns = __namespace( "Astro.Mechanism.Parallax" );

	/** @type {System.Cycle} */
	var Cycle                   = __import( "System.Cycle" );
	/** @type {Dandelion} */
	var Dand                    = __import( "Dandelion" );
	/** @type {Dandelion.IDOMObject} */
	var IDOMObject              = __import( "Dandelion.IDOMObject" );

	var Parallax = {
		totalCSSSlide: 0
	};

	var EnterFrame = (
		window.requestAnimationFrame
		|| window.webkitRequestAnimationFrame
		|| window.mozRequestAnimationFrame
		|| window.oRequestAnimationFrame
		|| window.msRequestAnimationFrame
		|| function( f ) { window.setTimeout( f, 1000 / 60 ); }
	);

	var cssSlide = function( element, slide_index, distance )
	{
		// The concept is drawn in physical book, will make a blog post for this:)
		var name, s;
		if( !( s = Parallax[ name = "s" + slide_index ] ) )
		{
			s = Parallax[name] = [];
			Parallax.totalCSSSlide ++;
		}
		return (
			s[ s.length ] = {
				element: Dand.wrapc( "parallaxCSSSlideLayer slideTransitionOverride", element )
				// vertical range
				, verticalRange: distance.upperLimit - distance.lowerLimit - 100
				// horizontal range
				, horizontalRange: distance.rightLimit - distance.leftLimit - 100
			}
		).element
		;
	};

	var verticalSlideTo = function( slide_index )
	{
		var s, l = Parallax.totalCSSSlide;
		for( var i = 0; i < l; i ++ )
		{
			if(i <= slide_index)
			{
				s = Parallax["s" + i];
				for( var j = 0, k; j < s.length; j ++ )
				{
					k = s[j];
					k.element.style.top = String(-k.verticalRange*((slide_index + 1))) + "%";
				}
			}
			else break;
		}
	};

	var attach = function ( eDispatcher, sSupplier, opacityModifier )
	{
		var opacityModifier = ( opacityModifier == undefined ) ? 1 : opacityModifier + 0;
		var s, l = Parallax.totalCSSSlide;

		for( var i = 0; i < l; i ++ )
		{
			s = Parallax["s" + i];
			for( var j = 0, k; j < s.length; j ++ )
			{
				k = s[j];
				k.element.style.opacity = ( ( 0.35 + 0.55 * i / l ) * opacityModifier ) + "";
			}
		}

		var cp = 0;
		var pp = 0;
		var _lock = false;
		var animate = function()
		{
			var p = sSupplier.scrollTop/(sSupplier.scrollHeight - sSupplier.clientHeight);
			cp = 0.85 * cp + p * 0.15;
			cp = 0.0001 * Math.round( cp * 10000 );

			if ( pp == cp )
			{
				_lock = false;
				return;
			}

			for( var i = 0; i < l; i ++ )
			{
				s = Parallax["s" + i];
				for( var j = 0, k; j < s.length; j ++ )
				{
					k = s[j];
					k.element.style.transform = "translate(0," + ( -k.verticalRange * ( ( j + 1 ) * cp ) ).toFixed( 2 ) + "%)";
				}
			}

			pp = cp;
			EnterFrame( animate );
		};

		var dispatchAnima = function()
		{
			if( _lock ) return;
			_lock = true;
			EnterFrame( animate );
		};

		IDOMObject( eDispatcher ).addEventListener( "Scroll", dispatchAnima );
	};

	ns[ NS_EXPORT ]( EX_FUNC, "cssSlide", cssSlide );
	ns[ NS_EXPORT ]( EX_FUNC, "verticalSlideTo", verticalSlideTo );
	ns[ NS_EXPORT ]( EX_FUNC, "attach", attach );
})();