Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   Loading Image на JS (https://javascript.ru/forum/project/68003-loading-image-na-js.html)

exec 20.03.2017 08:44

Loading Image на JS
 
Создаём loading image средствами Javascript.

Демо на jsfiddle

<body></body>

<script>
(function () {

"use strict";

function _circle(top, left, size) {
	var circle = document.createElement("DIV");
	circle.style =	"width: " + size + "px; height: " + size + "px; border-radius: " + (size * 10) + "px; position: fixed;" +
			"background-color: #000000; top: " + top + "px; left: " + left + "px";
	document.body.appendChild(circle);
	return circle;
}

function _default(settings, defaultProps) {
	if (!settings) settings = {};
	for (var i in defaultProps) if ( !(i in settings) ) settings[i] = defaultProps[i];
	return settings;
}

function _fx(circle, from, to, speed ) {
	var start = +new Date();
	fx();
	function fx() {
		var m = (+new Date() - start) / speed;
		if (m > 1) m = 1; else setTimeout(fx, 17);
		circle.style.width = circle.style.height = (from + (to - from) * m) + "px";
	}
}

function _init(settings) {
	settings = _default(settings, {
		top : 100,
		left : 100,
		size : 10,
		speed : 200,
		circles : 8,
		dispersion : 2,
		by : 5
	});

	var circles = [];

	var j = 0;

	for (var i = 0; i < settings.circles; i++) {
		circles.push(_circle(	settings.top + Math.sin(i / settings.circles * 6.28) * settings.size * settings.dispersion,
					settings.left + Math.cos(i / settings.circles * 6.28) * settings.size * settings.dispersion,
					settings.size
		));
	}

	var timer = setInterval(function () {
		++j;
		_fx( circles[j % settings.circles], settings.size, settings.size + settings.by, settings.speed );
		_fx( circles[(j - 1) % settings.circles], settings.size + settings.by, settings.size, settings.speed );
	}, settings.speed);

	return {
		remove : function () {
			for (var i = 0; i < circles.length; i++) {
				document.body.removeChild(circles[i]);
			}
			clearInterval(timer);
		}
	};
}

window.LoadingImage = _init;

})();

LoadingImage({ top : 50, left : 50 });
</script>


Функция возвращает метод remove(), который удаляет все кружки и интервал анимации.

Также она принимает параметры (в скобках указаны параметры по умолчанию):

Код:

top, left (100, 100) - координаты куда вставлять
size (10) - размер кружков
speed (200) - скорость анимации
circles (8) - количество кружков
dispersion (2) - разброс
Например, если захочется сделать 16 кружков вместо 8, то dispersion лучше поставить 4, иначе кружки будут накладываться друг на друга. Чем больше dispersion, тем больше конечный loading image
by (5) - на сколько увеличивать кружок


рони 20.03.2017 09:30

exec,
а почему бы не использовать requestAnimationFrame вместо setInterval?

Alexandroppolus 20.03.2017 10:33

exec,

Прикольно, конечно, но сама идея в общем случае тупиковая - в любой момент дизайнер может придумать новую крутилку, которая не впишется в этот код. Так что лучше юзать старую добрую гифку, которую рисовальщик перерисует, если что :)

Хотя если ты сам себе дизайнер (манагер), то вполне.

exec 20.03.2017 12:27

Немного дописал код, главные изменения - теперь размер кружков меняется по цепочке (см. демо, параметр chain), а также можно менять opacity (параметр fade). Если fade больше нуля, у активных кружков opacity будет увеличиваться, если меньше нуля - то соответственно уменьшаться, в пример всё видно. Чтобы opacity не менялся вообще, fade следует поставить на 1.

<body></body>
<script>
(function () {

"use strict";

function _default(settings, defaultProps) {
	if (!settings) settings = {};
	for (var i in defaultProps) if ( !(i in settings) ) settings[i] = defaultProps[i];
	return settings;
}

function _fx(circle, from, to, speed, opacityFrom, opacityTo ) {
	var start = +new Date();
	fx();
	function fx() {
		var m = (+new Date() - start) / speed;
		if (m > 1) m = 1; else setTimeout(fx, 17);
		circle.style.width = circle.style.height = (from + (to - from) * m) + "px";
		if (opacityFrom) circle.style.opacity = opacityFrom + (opacityTo - opacityFrom) * m;
	}
}

function _init(settings) {
	settings = _default(settings, {
		top : 100,
		left : 100,
		size : 10,
		speed : 200,
		circles : 8,
		dispersion : 2,
		by : 5,
		color : "#000000",
		chain : 1,
		fade : -0.5
	});

	var reverse = false;

	if (settings.fade < 0) {
		settings.fade = -settings.fade;
		reverse = true;
	}

	var x4 = reverse ? 1 : settings.fade;
	var x3 = reverse ? -1 : 1;
	var x2 = settings.size * settings.dispersion;
	var x1 = 2 * x2 + settings.size - 1;

	var circles = [];
	var wrap = document.createElement("DIV");
	wrap.style.cssText =	"position: absolute; top: " + (settings.top - x2) + "px; left: " +
				(settings.left - x2) + "px; width: " + x1 + "px; height:" + x1 + "px" ;

	var j = -1;

	for (var i = 0; i < settings.circles; i++) {
		var circle = document.createElement("DIV");
		circle.style.cssText =	"width: " + settings.size + "px; height: " + settings.size + "px; position: fixed;" +
					"background-color: " + settings.color + "; border-radius: " + (settings.size + settings.by) +
					"px; top: " + (settings.top + Math.sin(i / settings.circles * 6.28) * x2) + "px; left: " +
					(settings.left + Math.cos(i / settings.circles * 6.28) * x2) + "px; opacity: " +
					(reverse ? 1 : settings.fade);
		wrap.appendChild(circle);
		circles.push(circle);
	}

	document.body.appendChild(wrap);

	var timer = setInterval(function () {
		++j;
		_fx(
			circles[j % settings.circles],
			settings.size,
			settings.size + settings.by,
			settings.speed,
			x4,
			reverse ? settings.fade : 1 );
		for (var i = 1; i <= settings.chain; i++) {
			if ((j - i) % settings.circles < 0) continue;
			_fx(
				circles[(j - i) % settings.circles],
				settings.size + settings.by * (settings.chain - i + 1) / settings.chain,
				settings.size + settings.by * (settings.chain - i) / settings.chain,
				settings.speed,
				x4 + x3 * (1 - settings.fade) * (settings.chain - i + 1) / settings.chain,
				x4 + x3 * (1 - settings.fade) * (settings.chain - i) / settings.chain
			);
		}
	}, settings.speed);

	return {
		remove : function () {
			document.body.removeChild(wrap);
			clearInterval(timer);
		},
		image : wrap
	};
}

window.LoadingImage = _init;

})();

LoadingImage({ top : 50, left : 50, speed : 100, by : 10, color : "#007fff", size : 20, chain : 5, fade: -0.5 });

LoadingImage({ top : 50, left : 200, speed : 100, by : 10, color : "#007fff", size : 20, chain : 5, fade: 0.5 });

LoadingImage({ top: 50, left : 350, speed : 100, by : 8, color : "#007fff", size : 10, chain : 10, fade: 1, circles : 16, dispersion : 4 });
</script>

exec 21.03.2017 05:27

Окончательная версия, убраны некоторые баги, добавлен chainEasing, призванный управлять поведением элементов в цепочке.

Демо

psiklop 29.03.2017 17:08

Прикольно, мне понравилось

exec 30.03.2017 12:48

Эмуляция Солнечной системы

Пасхалка: если кликнуть на Солнце, оно взорвётся (станет красным гигантом), а планеты сойдут с орбит.

exec 02.04.2017 08:04

[][$=({}+(_=__=''))[++_|++_+_]+({}+__)[--_]+([][_]+__)[_]+(!_+__)[_-~_]+(!!_+'')[--_]+(!_+__)[++_]+(!!_+__)[++_]+({}+__)[_+ ++_]+(!!_+__)[+__]+({}+__)[_/_]+(!!_+__)[+!__]][$]((!--_+__)[--_]+(!++_+__)[_]+(!!++_+__)[_]+(!!--_+__)[--_]+(!!_+__)[--_]+(_[$]+__)[(++_+ ++_)*++_+ ++_+!![]+!![]]+(_[$]+__)[_*_])()

psiklop 03.04.2017 22:57

Я читал, когда солнце станет красным гигантом планеты не улетят, сгорят на своих орбитах, и да планет пока 8.

exec 05.04.2017 19:50

mtx.js 1.0

Пришла идея сделать jQuery-подобную библиотеку для работы с мат. объектами, начнём с матриц.

Тут же возникает вопрос: смещать ли нумерацию? Т.е. должен ли matrix[1][1] находить первый элемент первого столбца, а не второй элемент второго?


Часовой пояс GMT +3, время: 23:01.