Ресурсы: JavaScript-анимации Исходники урока
setTimeout() - позволяет запускать функцию через определённый промежуток времени.
Синтаксис:
Код
const tinerId = setTimeout(function() {
console.log('Hello');
}, 2000);
Первый параметр - это функция, которую нужно запустить, второй параметр - время в миллисекундах (например, 2000мс это 2 секунды), через которое запускается функция.
Для запускаемой функции можно также передавать что-либо в качестве третьего аргумента:
Код
const timerId = setTimeout(function(text) {
console.log(text);
}, 2000, 'Hello');
Строка
Hello передастся в переменную
text функции. Можно также передавать готовую функцию.
Например, создадим функцию и назовём её
logger Код
function logger() {
console.log('text');
}
И теперь её можно использовать, передав в качестве аргумента:
Код
const timerId = setTimeout(logger, 2000);
По истечении 2 секунд сработает функция
logger и в консоль выведется строка '
text'
Почему изначально мы положили
setTimeout в переменную
timerId? Ведь и без этого всё также отработает.
Всё дело в том, что когда мы передаём
setTimeout в переменную, мы записываем тем самым числовой идентификатор этого таймера, чтобы иметь возможность их потом как-то останавливать.
Сбросить
setTimeout можно с помощью команды
clearInterval() Код
clearInterval(timerId);
Как вариант это можно реализовать при клике на кнопку.
К примеру, на странице у нас есть кнопка с классом .
btn, получим её:
Код
const btn = document.querySelector('.btn');
Добавляем ей обработчик события клика и говорим, что при клике на кнопку, через 2 секунды запустится функция
logger Код
btn.addEventListener('click', () => {
const timerId = setTimeout(logger, 2000);
});
function logger() {
console.log('text');
}
Если нужно, чтобы функция выполнялась не один раз, а много, через определённое количество времени, то используется метод
setInterval().
Если в коде выше заменить
setTimeout на
setInterval, то при клике на кнопку через каждые 2 секунды в консоль будет выводиться сообщение '
text'
Как же нам использовать переменную
timerId, ведь она локальная и видна только в блоке кода анонимной функции обработчика события?
Для этого в самом начале кода первоначально её просто объявляют как глобальную переменную, но без всякого значения:
Код
const btn = document.querySelector('.btn');
let timerId;
Далее, внутри обработчика события мы ей присваиваем значение:
Код
btn.addEventListener('click', () => {
timerId = setTimeout(logger, 2000);
});
И теперь мы можем использовать эту переменную вне блока кода обработчика события, например, чтобы остановить таймер:
Код
const btn = document.querySelector('.btn');
let timerId;
btn.addEventListener('click', () => {
timerId = setTimeout(logger, 2000);
});
function logger() {
console.log('text');
}
clearInterval(timerId);
Но в данном коде
clearInterval не сработает, потому что в
timerId еще ничего нет, там изначально значение
undefined.
А сделаем следующее: внутри функции
logger мы будем отслеживать сколько раз повторился
setInterval, ну и конечно для этого нам понадобится переменная-итератор
i, которая будет счётчиком с начальным нулевым значением:
Код
const btn = document.querySelector('.btn');
let timerId;
let i = 0;
btn.addEventListener('click', () => {
timerId = setTimeout(logger, 2000);
});
function logger() {
if (i === 3) {
clearInterval(timerId);
} else {
console.log('text');
i++;
}
}
Чем рекурсивный setTimeout лучше чем setInterval?
Рекурсия - это когда функция вызывает сама себя изнутри.
Вероятная проблема: когда работает
setInterval, он не учитывает, как долго будет работать функция внутри него.
Ведь ему всё равно, сколько по времени будет выполняться код функции. И если функция выполняет какие-то сложные трудозатратные операции, которые займут определённое время, например, 3 секунды, а интервал повторений у
setInterval, к примеру, будет 1 секунда.
Что будет в этом случае?
А будет так, что
setInterval уже не будет ждать потом 1 секунду, после того, как функция завершит работу, а сразу же начнет выполнять следующее повторение функции
logger.
Как мы думаем должно работать?
1 секунда задержка - выполняется функция - 1 секунда задержка - выполняется функция.
А на самом деле будет так:
1 секунда задержка - выполняется 3 секунды функция - опять запуск функции, поскольку
setInterval думает, что 1 секунда задержки уже прошла.
Для решения этой проблемы используют
рекурсивный setTimeout Код
let id = setTimeout(function log() {
console.log('Hello');
id = setTimeout(log, 500);
}, 500);
Разница тут будет лишь в том, что запуск функции
log всегда будет строго через 0,5 секунды, как бы долго по времени не выполнялась функция, то есть:
500мс задержка - запуск функции
log - ожидание завершения работы функции - 500мс задержка - запуск функции снова.
Построение анимации
Нам необходимо создать анимацию движения зелёного квадратика из верхнего левого угла в нижний правый угол.
Анимация будет запускаться после нажатия на кнопку.
Сначала получаем кнопку:
Код
const btn = document.querySelector('.btn');
Далее начинаем писать функцию построения анимации:
Код
function myAnimation() {
}
В данном случае построение анимации будет реализовано несколько старым способом, сейчас для этого существуют гораздо более эффективные приёмы. Нам же нужно просто понять как можно использовать
setInterval на странице сайта.
Внутри нашей функции получаем наш зелёный квадратик по его классу:
Код
function myAnimation() {
const elem = document.querySelector('.box');
}
Помимо этого нам понадобится переменная позиции квадратика, с которой будет старт анимации.
Код
function myAnimation() {
const elem = document.querySelector('.box');
let pos = 0;
}
Далее добавляем функцию, которая будет запускаться через определённый промежуток времени:
Код
function myAnimation() {
const elem = document.querySelector('.box');
let pos = 0;
function frame() {
}
}
Внутри этой функции мы определяем условие, при котором анимация должна заканчиваться
Код
function myAnimation() {
const elem = document.querySelector('.box');
let pos = 0;
function frame() {
if (pos == 300) {
clearInterval();
} else {
pos++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
}
Смысл в том, что размеры контейнера, согласно файлу стилей, 300 х 300 пикселей, размеры квадратика внутри него 100 х 100 пикселей.
Для перемещения квадратика по дигонали нам нужно постоянно перемещать квадратик от левого и верхнего краёв контейнера на одинаковое значение.
Как только значение переменной
pos станет равным 300, анимация останавливается (потому что квадратик окажется в нижнем правом углу)
Нам осталось теперь запустить нашу функцию
frame через
setInterval, чтобы получить плавную анимацию
Код
function myAnimation() {
const elem = document.querySelector('.box');
let pos = 0;
const id = setInterval(frame, 10);
function frame() {
if (pos == 300) {
clearInterval(id);
} else {
pos++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
}
Не забываем в
clearInterval передать
id идентификатор таймера для его остановки при достижении значения 300 у переменной
pos.
Добавляем обработчик события на нашу кнопку:
Код
btn.addEventListener('click', myAnimation);
Цитата
Что у нас в итоге получилось, смотрим
здесь
Добавлять комментарии могут только зарегистрированные пользователи.