Skip to content
 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Сегодня мы будем делать код для "Анимастера". Это скрипт, позволяющий создавать и управлять анимациями.

Уже написано несколько функций, делающих элементарные анимации.

При клике на кнопку play возле названия анимации запустят ее.

  1. Создай функцию с названием animaster

  2. Сейчас функции-анимации (move, fadeIn, scale) лежат в глобальной области видимости и имеют очень простые названия — их легко случайно переопределить. Поэтому спрячь их определения внутрь функции animaster. Функция animaster должна возвращать объект с методами для запуска разных анимаций. Сделай так, чтобы кнопки на страничке все еще показывали анимацию.

Использовать анимации теперь можно будет вот так:

animaster().scale(element, 500, .8)
  1. По аналогии с функцией fadeIn создай функцию fadeOut, скрывающую элемент.

  2. Мы хотим, немного облегчить жизнь пользователям анимастера, поэтому напишем для них несколько сложных анимаций. Сложные анимации состоят из нескольких простых, запущенных в правильном порядке и в нужное время. Добавь в интерфейс анимастера три новые анимации. Не забудь сделать так, чтобы с html-странички можно было их запустить. Вот такие анимации должен реализовывать анимастер:

    • moveAndHide — блок должен одновременно сдвигаться на 100 пикселей вправо и на 20 вниз, а потом исчезать. Метод на вход должен принимать продолжительность анимации. При этом 2/5 времени блок двигается, 3/5 — исчезает.
    • showAndHide — блок должен появиться, подождать и исчезнуть. Каждый шаг анимации длится 1/3 от времени, переданного аргументом в функцию.
    • heartBeating — имитация сердцебиения. Сначала элемент должен увеличиться в 1,4 раза, потом обратно к 1. Каждый шаг анимации занимает 0,5 секунды. Анимация должна повторяться бесконечно.
  3. Сделай возможность отключать анимацию сердцебиения:

    • сделай, чтобы метод heartBeating возвращал объект с методом stop
    • при вызове метода stop анимация должна прекращаться (скорее всего, нужно останавливать таймер, которым ты анимацию запускаешь)
    • добавь в разметку кнопку stop по аналогии с кнопкой play
    • в коде добавь обработчик клика по аналогии с тем, как это сделано для кнопки play. Обработчик должен вызывать метод stop анимации
  4. Сделай функции отмены для каждой элементарной операции. Создай служебные (не доступные снаружи анимастера) функции resetFadeIn, resetFadeOut и resetMoveAndScale. Все эти функции принимают на вход элемент, на котором надо сбросить состояние.

resetFadeIn и resetFadeOut должны менять обратно css-классы в classList — каждая из них должны убирать все дописанные стили, устанавливая их в null:

element.style.заданныйАнимациейСтиль = null;
  1. Сделай кнопку reset для анимации moveAndHide по аналогии с кнопкой stop из одного из предыдущих пунктов. При нажатии на кнопку reset последующие шаги анимации должны отменяться аналогично stop из heartBeating, а элемент должен мгновенно вернуться в исходное состояние с помощью функций из предыдущего пункта.

  2. Сделай так, чтобы анимацию move можно было вызвать не только так:

animaster().move(element, 500, {x: 20, y: 20});

Но и так:

animaster().addMove(500, {x: 20, y:20}).play(element);

Для этого:

  • добавь методы addMove и play в объект, возвращаемый функцией animaster
  • в объекте, возвращаемом из анимастера, должно появиться поле _steps — массив шагов анимации (в начале пустой). Поле _steps — приватное. Приватные поля по договоренности между разработчиками начинаются с нижнего подчеркивания.
  • метод addMove должен возвращать this (то есть тот объект анимастера, который вернулся из вызова animaster)
  • метод addMove должен добавлять в поле this._steps новый шаг анимации.

Структуру, в которой будешь хранить каждый шаг, придумай сам. Каждый шаг должен содержать следующую информацию:

  • название элементарной операции (move, fadeIn)
  • продолжительность шага в миллисекундах
  • дополнительные параметры (смещение для move, соотношение для scale)
  • метод play должен принимать элемент, который будем анимировать, в качестве аргумента
  • метод play должен выполнять по очереди все шаги анимации, которые лежат в массиве this._steps, применяя их к переданному ему элементу.
  1. Сделай так, чтобы метод move работал на написанных на предыдущем шаге методах.

  2. Сделай по аналогии с методом addMove методы addScale, addFadeIn и addFadeOut. Перепиши соответствующие анимации, чтобы они переиспользовали эти методы.

  3. Теперь у тебя должно быть возможным такое использование:

const customAnimation = animaster()
    .addMove(200, {x: 40, y: 40})
    .addScale(800, 1.3)
    .addMove(200, {x: 80, y: 0})
    .addScale(800, 1)
    .addMove(200, {x: 40, y: -40})
    .addScale(800, 0.7)
    .addMove(200, {x: 0, y: 0})
    .addScale(800, 1);
customAnimation.play(element);

В этот момент анимация запускается, элемент перемещается по четырем точкам и меняет размеры. В конце элемент возвращается в исходную точку. Если customAnimation.play(element) запустить несколько раз с разными элементами, то анимации должны работать.

  1. Перепиши сложные анимации moveAndHide, showAndHide и heartBeating на использование новых методов add... и play. Чтобы сделать showAndHide, добавь метод addDelay, добавляющий шаг, в котором ничего не происходит в течение заданного времени. Чтобы сделать heartBeating, добавь в play в аргументы флаг cycled, означающий, что шаги анимации надо повторять бесконечно.

  2. Метод play должен возвращать объект с методом stop (применяется для heartBeating) и reset. Метод reset должен возвращать элемент в исходное состояние (то, которое было до анимации):

  • если элемент был скрыт, то скрыть его
  • если был показан, то показать
  • если элемент был сдвинут или его размер изменен, то вернуть в исходное состояние

Для этого воспользуйся функциями отмены элементарных операций.

  1. Добавь метод buildHandler, результат которого можно сразу передать в addEventListener:
const worryAnimationHandler = animaster()
    .addMove(200, {x: 80, y: 0})
    .addMove(200, {x: 0, y: 0})
    .addMove(200, {x: 80, y: 0})
    .addMove(200, {x: 0, y: 0})
    .buildHandler();

document
    .getElementById('worryAnimationBlock')
    .addEventListener('click', worryAnimationHandler);

Особенность addEventListener в том, что если ему во второй параметр передать не стрелочную функцию, то в качестве контекста вызова this он передаст ей DOM-элемент с которым происходит событие.

  1. * Реализуй какую-нибудь еще анимацию, которой пока нет. В качестве идей, можешь использовать этот сайт: http://leaverou.github.io/animatable/ Если на этой странице нажать кнопку "Animate All", становится весело =)

  2. * Сейчас есть проблема, что если написать вот так:

const a = animaster().addMove(111, {x: 10, y: -10})
const b = a.addFadeOut(400);

То при запуске a.play(el), выполнится и перемещение и исчезновение, хотя это и не ожидается.

Сделай так, чтобы в такой записи a и b представляли собой разные наборы анимаций и можно было на любом шаге в цепи сохранить анимацию и воспользоваться ею.

About

animaster task

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages