Page 1 of 1

HTML JavaScript Metro style loading bar

Posted: Wed Jun 06, 2012 11:44 am
by Chris

Code: Select all

<!DOCTYPE html>
<html>
	<head>
		<title>HTML Metro Loading Bar</title>
		<style type="text/css">
		.loading-bar .block {
			background: #00F;
		}
		</style>
	<head>

	<body>

		<script type="text/javascript">
		LoadingBar = function(blocks)
		{
			this.numBlocks = blocks == undefined || typeof blocks != 'number' ? 5 : blocks;

			this.element = document.createElement('div');
			this.element.className = 'loading-bar';

			this.element.style.width = window.innerWidth + 'px';
			this.element.style.position = 'absolute';
			this.element.style.left = '0';
			this.element.style.right = '0';
			this.element.style.overflow = 'hidden';
			this.element.style.height = '5px';

			this.slowDownRange = Math.floor((parseInt(this.element.style.width)/3)/2);
			this.slowDownAreaStart = Math.floor( parseInt(this.element.style.width)/2 - this.slowDownRange);
			this.slowDownAreaStop = Math.floor( parseInt(this.element.style.width)/2 + this.slowDownRange);

			this.blocks = [];

			for( var i = 0; i < this.numBlocks; i++ )
			{
				this.blocks.push(new LoadingBarBlock(this));
				this.element.appendChild(this.blocks[i].element);
			}

			this.start = function()
			{
				for( var i in this.blocks )
				{
					var _this = this,
						_waitTime = this.slowDownRange*i,
						_i = i;

					(function(me, waitTime, i){
						
						var _this = me,
							_waitTime = waitTime,
							_i = i;

						setTimeout( function()
						{
							_this.blocks[_i].element.style.left = (_i*-parseInt(_this.blocks[_i].element.style.height)/2) + 'px';
							_this.blocks[_i].element.style.display = 'block';
							_this.blocks[_i].move();
						}, _waitTime);

					})(_this,_waitTime,_i)
				}
			}

			this.stop = function()
			{
				for( var i in this.blocks )
				{
					clearTimeout(this.blocks[i].moveTimeout);
					this.blocks[i].element.style.display = 'none';
				}
			}
		}

		LoadingBarBlock = function(loadingBar)
		{
			this.container = loadingBar;

			this.element = document.createElement('div');
			this.element.className = 'block';
			this.element.style.position = 'absolute';

			this.element.style.height = this.container.element.style.height;
			this.element.style.width = this.container.element.style.height;
			
			this.moveTimeout = null;

			this.move = function()
			{
				if( parseInt(this.element.style.left) >= this.container.slowDownAreaStart && parseInt(this.element.style.left) <= this.container.slowDownAreaStop )
				{
					this.displacementSpeed = 3;
				}
				else
				{
					this.displacementSpeed = 6;
				}

				this.element.style.left = (parseInt(this.element.style.left) + this.displacementSpeed) + 'px';

				if( parseInt(this.element.style.left) >= parseInt(this.container.element.style.width) ) this.element.style.left = '0px';

				var _this = this;
				this.moveTimeout = setTimeout( function(){ _this.move() }, 10);
			}
		}

		var lol = new LoadingBar(5);

		document.body.appendChild(lol.element);

		lol.start();

		</script>

	</body>
</html>
http://pastebin.com/wkFPvT2e

Re: HTML JavaScript Metro style loading bar

Posted: Thu Jun 07, 2012 10:43 am
by Chris
Improved:

Code: Select all

<!DOCTYPE html>
<html>
    <head>
        <title>HTML Metro Loading Bar</title>
        <style type="text/css">
        body { background: #000 ;}
        .block {
            background: #0fF;
            height: 5px;
            width: 5px;
        }
        </style>
    <head>
    <body>
        <script type="text/javascript">
		LoadingBar = function (args /* { element : document element, numBlocks : integer } */) {

		    var args = args == undefined ? { numBlocks: this.numBlocks, element: document.createElement('div')} : args;

		    this.numBlocks = args.numBlocks == undefined ? this.numBlocks : typeof args.numBlocks == 'number' ? args.numBlocks : this.numBlocks;
		    this.element = args.element == undefined ? document.createElement('div') : args.element;

		    this.element.className = 'loading-bar';
		    this.element.style.position = 'absolute';
		    this.element.style.left = '0';
		    this.element.style.right = '0';
		    this.element.style.overflow = 'hidden';
		    this.setDimensions();
		    var _this = this;
		    window.addEventListener('resize', function () { _this.setDimensions() });
		    return this;
		}

		LoadingBar.prototype = {

		    constructor: LoadingBar,
		    interval: null,
		    loops: 0,
		    loopPauseDuration: 1000,
		    element: null,
		    numBlocks: 5,
		    animationSpeed: 10,
		    blockDisplacemenetSpeed: 6,
		    slowDownPercentage: 50,
		    slowDownRange: 0,
		    slowDownAreaStart: 0,
		    slowDownAreaStop: 0,

		    setDimensions: function () {
		        this.element.style.width = window.innerWidth + 'px';
		        this.slowDownRange = Math.floor((parseInt(this.element.style.width) / 3));
		        this.slowDownAreaStart = this.slowDownRange;
		        this.slowDownAreaStop = this.slowDownRange * 2;
		    },

		    addBlock: function () {
		        var block = document.createElement('div');
		        block.className = 'block';
		        block.style.position = 'fixed';
		        block.style.display = 'block';
		        this.element.appendChild(block);
		        return block;
		    },

		    removeBlock: function (index) {
		        this.element.removeChild(this.element.getElementsByClassName('block')[index]);
		    },

		    clearBlocks: function () {
		        while (this.element.hasChildNodes()) {
		            this.element.removeChild(this.element.lastChild);
		        }
		    },

		    start: function () {
		        this.reset();
		        for (var i = 0; i < this.numBlocks; i++) {
		            this.addBlock().style.left = Math.floor(-1 * (1 + i) * (this.slowDownRange / this.numBlocks)) + 'px';
		        }
		        var pause = this.loops == 0 ? 0 : this.loopPauseDuration,
		            _this = this;
		        this.loops++;
		        this.interval = setTimeout(function () { _this.animate(); }, pause);
		        return this;
		    },

		    animate: function () {
		        var _this = this,
		            blocks = this.element.getElementsByClassName('block');

		        if (blocks.length == 0) return this.start();

		        for (var i in blocks) {
		            if (typeof blocks[i] == 'object') {
		                var x = parseInt(blocks[i].style.left),
		                    displacementSpeed = this.blockDisplacemenetSpeed;

		                if (x >= this.slowDownAreaStart && x <= this.slowDownAreaStop) {
		                    displacementSpeed = Math.floor(displacementSpeed / (100 / this.slowDownPercentage));
		                }
		                blocks[i].style.left = (x + displacementSpeed) + 'px';

		                if (parseInt(blocks[i].style.left) >= parseInt(this.element.style.width)) {
		                    this.removeBlock(i)
		                }
		            }
		        }
		        this.interval = setTimeout(function () { _this.animate(); }, _this.animationSpeed);
		    },

		    reset: function()
		    {
		        this.clearBlocks();
		        clearTimeout(this.interval);
		    },

		    stop: function () {
		        this.loops = 0;
		        this.clearBlocks();
		        clearTimeout(this.interval);
		    }
		}
        
        document.body.appendChild(new LoadingBar().start().element);
        </script>
    </body>
</html>
http://pastebin.com/dFDfD8yJ

Re: HTML JavaScript Metro style loading bar

Posted: Thu Jun 07, 2012 1:47 pm
by hallsofvallhalla
very sweet!

Re: HTML JavaScript Metro style loading bar

Posted: Thu Jun 07, 2012 9:30 pm
by Jackolantern
I had to try it out (having a Windows Phone and all lol). Very nice! This could be cool wrapped up in a module to use as a page or AJAX loading animation :)

Re: HTML JavaScript Metro style loading bar

Posted: Fri Jun 08, 2012 7:58 am
by Chris
I'm working on a Metro UI extension for SignalR for work without WinJS. Going to make it all open source.

Re: HTML JavaScript Metro style loading bar

Posted: Sat Jun 09, 2012 10:44 pm
by Jackolantern
Very nice! Metro is coming in a big way to the computing scene, and it represents the biggest change in the Windows UI since Windows 95. Developers and designers are going to be scrambling when it goes global to create packages to integrate into the Metro look, so now is a good time to launch a project to do just that and get a jump on it 8-)