Javascript бегущий огонек
Понадобилось мне на днях сделать "бегущий огонек" на javascript, без jQuery и каких - либо зависимостей. После недолгого поиска в интернете решил сделать сам. Получился некий цикличный итератор над коллекцией DOM-элементов с таймаутом. Кому нужно - забирайте.
Так же было решено вынести всю специфику в клиентский код, потому как может кому то понадобится эффект не именно бегущий огонек, а допустим какой другой цикличный эффект над набором DOM-элементов, например подпрыгивание чего - либо или появление или исчезание, или любая другая логика, укладывающаяся в схему:
while true:
берем следующий элемент;
если элементов больше нет - берем первый элемент;
применяем к элементу первую ф-цию;
ждем таймаут;
применяем к элементу вторую ф-цию;
ждем таймаут;
endwhile;
В общем оставил чисто абстракцию, реализующую задачу описанную выше, но для примера "бегущий огонек" подойдет как раз кстати. В примере клиентские функции при вызове будут просто делать: одна - устанавливать класс lightOn, а вторая - убирать этот класс у текущего элемента. Так мы добьемся эффекта "бегущий огонек".
Бегущий огонек демо
Бегущий огонек код
"use strict";
/**
* Цикличный итератор с временной задержкой.
*
* @param {NodeList|HTMLElement[]} oNodeList - массив или NodeList элементов
* над которыми нужно циклично применять функции callbackStart и callbackEnd
* @param {Function} callbackStart - функция обр. вызова, вызываемая при
* переходе на элемент, получит текущий элемнт как параметр.
* @param {Function} callbackEnd - функция обр. вызова, вызываемая при
* уходе с элемента, получит текущий элемнт как параметр.
* @param {number} speed - временная задержка в мсек.
*/
function TimeoutIterator(oNodeList, callbackStart, callbackEnd, speed) {
var _index = 0,
_interval = 0;
// Предохранитель от возможного вызова без "new"
if (!(this instanceof TimeoutIterator.prototype.constructor)) {
return new TimeoutIterator(oNodeList, callbackStart, callbackEnd, speed);
}
/**
* Стартовая операция.
*
* Её предназначение вызвать или не вызвать 1-й коллбэк (callbackStart),
* а затем спустя заданный интервал (speed) вызвать финишную операцию.
*
* @param {HTMLElement} element - текущий элемент набора
*/
function startAction(element) {
// если передан первый коллбэк - вызываем его:
callbackStart && callbackStart(element);
// с указанной задержкой...
window.setTimeout(function () {
// вызываем вторую операцию.
stopAction(element);
}, speed);
}
/**
* Финишная операция.
*
* Её предназначение вызвать или не вызвать 2-й коллбэк (callbackEnd).
*
* @param {HTMLElement} element - текущий элемент набора
*/
function stopAction(element) {
callbackEnd && callbackEnd(element);
}
/**
* Запустить.
*/
this.run = function () {
// Предохранитель от повторного запуска
// уже работающего экземпляра.
if (_interval > 0) {
return;
}
_interval = window.setInterval(function () {
// Для "удержания" индекса текущего элемента
// в пределах размера oNodeList применяем
// операцию деления по модулю.
_index %= oNodeList.length;
// Запускаем стартовую операцию:
startAction(oNodeList[_index]);
_index++;
}, speed);
};
/**
* Остановить.
*/
this.stop = function () {
// Просто очистим _interval
window.clearInterval(_interval);
_interval = 0;
};
}
Использование "бегущий огонек"
Под "бегущий огонек" нам понадобится примерно следующая разметка:
<p>
<button id="runner" type="button">СТАРТ</button>
<button id="stop" type="button">СТОП</button>
</p>
<div id="iter-container">
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
</div>
А сам скрипт вызываем следующим образом:
/** @type {NodeList} elementCollection - набор элементов для "бегущего огонька" */
var elementCollection = document.getElementById("iter-container")
.getElementsByTagName("DIV"),
lr = TimeoutIterator(
elementCollection,
/**
* стартовая ф-ция: просто устанвливает имя класса lightOn
* @param {HTMLElement} element - текущий элемент набора
*/
function (element) {
element.className += (element.className.length) ?
" lightOn" : "lightOn";
},
/**
* финишная ф-ция: просто убирает имя класса lightOn
* @param {HTMLElement} element - текущий элемент набора
*/
function (element) {
element.className = element.className.replace(/\s?lightOn/, "");
},
/* задержка в мсек. */
50
);
/* "Вешаем" обработчик для запуска действия */
document.getElementById("runner").onclick = function () {
lr.run();
};
/* "Вешаем" обработчик для остановки действия */
document.getElementById("stop").onclick = function () {
lr.stop();
};
Информация копипастерам
Внимание! Копирование контента с сайта, возможно только с разрешения администратора. Т.е. Меня! Я скорее всего разрешу Вам это сделать, в обмен на живую ссылку, на статью оригинал.
Javascript бегущий огонек