diff --git a/README.md b/README.md index c044e46..0eca507 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ При клике на кнопку play возле названия анимации запустят ее. -1. Создай функцию с названием `animaster` ++++1. Создай функцию с названием `animaster` -2. Сейчас функции-анимации (`move`, `fadeIn`, `scale`) лежат в глобальной области видимости и имеют очень простые названия — их легко случайно переопределить. Поэтому спрячь их определения внутрь функции `animaster`. Функция `animaster` должна возвращать объект с методами для запуска разных анимаций. Сделай так, чтобы кнопки на страничке все еще показывали анимацию. ++++2. Сейчас функции-анимации (`move`, `fadeIn`, `scale`) лежат в глобальной области видимости и имеют очень простые названия — их легко случайно переопределить. Поэтому спрячь их определения внутрь функции `animaster`. Функция `animaster` должна возвращать объект с методами для запуска разных анимаций. Сделай так, чтобы кнопки на страничке все еще показывали анимацию. Использовать анимации теперь можно будет вот так: @@ -14,22 +14,22 @@ animaster().scale(element, 500, .8) ``` -3. По аналогии с функцией `fadeIn` создай функцию `fadeOut`, скрывающую элемент. ++++3. По аналогии с функцией `fadeIn` создай функцию `fadeOut`, скрывающую элемент. -4. Мы хотим, немного облегчить жизнь пользователям анимастера, поэтому напишем для них несколько сложных анимаций. Сложные анимации состоят из нескольких простых, запущенных в правильном порядке и в нужное время. Добавь в интерфейс анимастера три новые анимации. Не забудь сделать так, чтобы с html-странички можно было их запустить. Вот такие анимации должен реализовывать анимастер: ++++4. Мы хотим, немного облегчить жизнь пользователям анимастера, поэтому напишем для них несколько сложных анимаций. Сложные анимации состоят из нескольких простых, запущенных в правильном порядке и в нужное время. Добавь в интерфейс анимастера три новые анимации. Не забудь сделать так, чтобы с html-странички можно было их запустить. Вот такие анимации должен реализовывать анимастер: - `moveAndHide` — блок должен одновременно сдвигаться на 100 пикселей вправо и на 20 вниз, а потом исчезать. Метод на вход должен принимать продолжительность анимации. При этом 2/5 времени блок двигается, 3/5 — исчезает. - `showAndHide` — блок должен появиться, подождать и исчезнуть. Каждый шаг анимации длится 1/3 от времени, переданного аргументом в функцию. - `heartBeating` — имитация сердцебиения. Сначала элемент должен увеличиться в 1,4 раза, потом обратно к 1. Каждый шаг анимации занимает 0,5 секунды. Анимация должна повторяться бесконечно. -5. Сделай возможность отключать анимацию сердцебиения: ++++5. Сделай возможность отключать анимацию сердцебиения: - сделай, чтобы метод `heartBeating` возвращал объект с методом `stop` - при вызове метода `stop` анимация должна прекращаться (скорее всего, нужно останавливать таймер, которым ты анимацию запускаешь) - добавь в разметку кнопку stop по аналогии с кнопкой play - в коде добавь обработчик клика по аналогии с тем, как это сделано для кнопки play. Обработчик должен вызывать метод `stop` анимации -6. Сделай функции отмены для каждой элементарной операции. Создай служебные (не доступные снаружи анимастера) функции `resetFadeIn`, `resetFadeOut` и `resetMoveAndScale`. Все эти функции принимают на вход элемент, на котором надо сбросить состояние. ++-6. Сделай функции отмены для каждой элементарной операции. Создай служебные (не доступные снаружи анимастера) функции `resetFadeIn`, `resetFadeOut` и `resetMoveAndScale`. Все эти функции принимают на вход элемент, на котором надо сбросить состояние. `resetFadeIn` и `resetFadeOut` должны менять обратно css-классы в classList — каждая из них должны убирать все дописанные стили, устанавливая их в `null`: @@ -37,9 +37,9 @@ animaster().scale(element, 500, .8) element.style.заданныйАнимациейСтиль = null; ``` -7. Сделай кнопку reset для анимации `moveAndHide` по аналогии с кнопкой stop из одного из предыдущих пунктов. При нажатии на кнопку reset последующие шаги анимации должны отменяться аналогично stop из `heartBeating`, а элемент должен мгновенно вернуться в исходное состояние с помощью функций из предыдущего пункта. ++++7. Сделай кнопку reset для анимации `moveAndHide` по аналогии с кнопкой stop из одного из предыдущих пунктов. При нажатии на кнопку reset последующие шаги анимации должны отменяться аналогично stop из `heartBeating`, а элемент должен мгновенно вернуться в исходное состояние с помощью функций из предыдущего пункта. -8. Сделай так, чтобы анимацию `move` можно было вызвать не только так: ++-8. Сделай так, чтобы анимацию `move` можно было вызвать не только так: ``` animaster().move(element, 500, {x: 20, y: 20}); @@ -67,9 +67,9 @@ animaster().addMove(500, {x: 20, y:20}).play(element); - метод `play` должен принимать элемент, который будем анимировать, в качестве аргумента - метод `play` должен выполнять по очереди все шаги анимации, которые лежат в массиве `this._steps`, применяя их к переданному ему элементу. -9. Сделай так, чтобы метод `move` работал на написанных на предыдущем шаге методах. ++-9. Сделай так, чтобы метод `move` работал на написанных на предыдущем шаге методах. -10. Сделай по аналогии с методом `addMove` методы `addScale`, `addFadeIn` и `addFadeOut`. Перепиши соответствующие анимации, чтобы они переиспользовали эти методы. ++-10. Сделай по аналогии с методом `addMove` методы `addScale`, `addFadeIn` и `addFadeOut`. Перепиши соответствующие анимации, чтобы они переиспользовали эти методы. 11. Теперь у тебя должно быть возможным такое использование: diff --git a/index.html b/index.html index 6546475..f570671 100644 --- a/index.html +++ b/index.html @@ -13,6 +13,13 @@

fadeIn

+
+
+

fadeOut

+ +
+
+

move

@@ -27,6 +34,29 @@

scale

+
+
+

moveAndHide

+ + +
+
+
+
+
+

showAndHide

+ +
+
+
+
+
+

heartBeating

+ + +
+
+
diff --git a/index.js b/index.js index 61e55f6..a347855 100644 --- a/index.js +++ b/index.js @@ -4,55 +4,93 @@ function addListeners() { document.getElementById('fadeInPlay') .addEventListener('click', function () { const block = document.getElementById('fadeInBlock'); - fadeIn(block, 5000); + // animaster().fadeIn(block, 5000); + animaster().addFadeIn(5000).play(block); }); document.getElementById('movePlay') .addEventListener('click', function () { const block = document.getElementById('moveBlock'); - move(block, 1000, {x: 100, y: 10}); + animaster().move(block, 1000, {x: 100, y: 10}); }); document.getElementById('scalePlay') .addEventListener('click', function () { const block = document.getElementById('scaleBlock'); - scale(block, 1000, 1.25); + animaster().scale(block, 1000, 1.25); }); -} -/** - * Блок плавно появляется из прозрачного. - * @param element — HTMLElement, который надо анимировать - * @param duration — Продолжительность анимации в миллисекундах - */ -function fadeIn(element, duration) { - element.style.transitionDuration = `${duration}ms`; - element.classList.remove('hide'); - element.classList.add('show'); -} + document.getElementById('fadeOutPlay') + .addEventListener('click', () => { + const block = document.getElementById('fadeOutBlock'); + animaster().fadeOut(block, 5000); + }); -/** - * Функция, передвигающая элемент - * @param element — HTMLElement, который надо анимировать - * @param duration — Продолжительность анимации в миллисекундах - * @param translation — объект с полями x и y, обозначающими смещение блока - */ -function move(element, duration, translation) { - element.style.transitionDuration = `${duration}ms`; - element.style.transform = getTransform(translation, null); -} + document.getElementById('moveAndHide') + .addEventListener('click', () => { + const block = document.getElementById('moveAndHideBlock'); + animaster().moveAndHide(block, 5000, {x: 100, y: 20}); + }); -/** - * Функция, увеличивающая/уменьшающая элемент - * @param element — HTMLElement, который надо анимировать - * @param duration — Продолжительность анимации в миллисекундах - * @param ratio — во сколько раз увеличить/уменьшить. Чтобы уменьшить, нужно передать значение меньше 1 - */ -function scale(element, duration, ratio) { - element.style.transitionDuration = `${duration}ms`; - element.style.transform = getTransform(null, ratio); + document.getElementById('showAndHide') + .addEventListener('click', () => { + const block = document.getElementById('showAndHideBlock'); + animaster().showAndHide(block, 5000); + }); + + document.getElementById('heartBeating') + .addEventListener('click', () => { + const block = document.getElementById('heartBeatingBlock'); + let anim = animaster().heartBeating(block); + + document.getElementById('heartBeatingStop') + .addEventListener('click', () => { + anim.stop() + }); + }); + + document.getElementById('resetMoveAndHide') + .addEventListener('click', () => { + const block = document.getElementById('moveAndHideBlock'); + animaster().resetMoveAndHide(block); + }); } +//#region +// /** +// * Блок плавно появляется из прозрачного. +// * @param element — HTMLElement, который надо анимировать +// * @param duration — Продолжительность анимации в миллисекундах +// */ +// function fadeIn(element, duration) { +// element.style.transitionDuration = `${duration}ms`; +// element.classList.remove('hide'); +// element.classList.add('show'); +// } + +// /** +// * Функция, передвигающая элемент +// * @param element — HTMLElement, который надо анимировать +// * @param duration — Продолжительность анимации в миллисекундах +// * @param translation — объект с полями x и y, обозначающими смещение блока +// */ +// function move(element, duration, translation) { +// element.style.transitionDuration = `${duration}ms`; +// element.style.transform = getTransform(translation, null); +// } + +// /** +// * Функция, увеличивающая/уменьшающая элемент +// * @param element — HTMLElement, который надо анимировать +// * @param duration — Продолжительность анимации в миллисекундах +// * @param ratio — во сколько раз увеличить/уменьшить. Чтобы уменьшить, нужно передать значение меньше 1 +// */ +// function scale(element, duration, ratio) { +// element.style.transitionDuration = `${duration}ms`; +// element.style.transform = getTransform(null, ratio); +// } +//#endregion + function getTransform(translation, ratio) { const result = []; if (translation) { @@ -63,3 +101,208 @@ function getTransform(translation, ratio) { } return result.join(' '); } + +function animaster() { + let animaster = {}; + animaster._steps = []; + + animaster.addFadeIn = function(duration) { + let currentStep = { + name: 'fadeIn', + duration: duration, + }; + + this._steps.push(currentStep); + return this; + } + + animaster.addFadeOut = function(duration) { + let currentStep = { + name: 'fadeOut', + duration: duration + }; + this._steps.push(currentStep); + return this; + } + + animaster.addMove = function(duration, translation) { + let currentStep = { + name: 'move', + duration: duration, + translation: translation + }; + + this._steps.push(currentStep); + return this; + } + + animaster.addScale = function(duration, ratio) { + let currentStep = { + name: 'scale', + duration: duration, + ratio: ratio + }; + this._steps.push(currentStep); + return this; + } + + animaster.play = function(element) { + for(let e of this._steps) { + switch(e.name) { + case 'fadeIn': + this.fadeIn(element, e.duration) + break; + case 'fadeOut': + break; + case 'move': + break; + case 'scale': + break; + } + } + } + + animaster.fadeIn = function(element, duration) { + element.style.transitionDuration = `${duration}ms`; + element.classList.remove('hide'); + element.classList.add('show'); + }; + + animaster.move = function(element, duration, translation) { + element.style.transitionDuration = `${duration}ms`; + element.style.transform = getTransform(translation, null); + }; + + animaster.scale = function(element, duration, ratio) { + element.style.transitionDuration = `${duration}ms`; + element.style.transform = getTransform(null, ratio); + }; + + animaster.fadeOut = function(element, duration){ + element.style.transitionDuration = `${duration}ms`; + element.classList.remove('show'); + element.classList.add('hide'); + }; + + animaster.resetFadeOut = function(element) { + element.classList.remove('hide'); + element.classList.add('show'); + }; + + animaster.resetFadeIn = function(element) { + // element.style.show = null + element.classList.remove('show'); + element.classList.add('hide'); + }; + + animaster.moveAndHide = function(element, duration, translation) { + this.move(element, duration * 2 / 5, translation); + this.fadeOut(element, duration * 3 / 5); + }; + + animaster.showAndHide = function showAndHide(element, duration) { + animaster().fadeIn(element, duration / 3);//переделать на animaster.add...().play...() + + setTimeout(() => { + animaster().fadeOut(element, duration / 3); + }, duration / 3); + + }; + + animaster.heartBeating= function(element) { + let timer = setInterval(() => { + this.scale(element, 500, 1.4); + setTimeout(() => { + this.scale(element, 500, 1); + }, 500); + }, 1000); + return { + stop() { + clearTimeout(timer); + } + } + }; + + animaster.resetMoveAndScale = function(element) { + this.move(element, 0, {x: 0, y: 0}); + this.scale(element, 0, 1); + }; + + animaster.resetMoveAndHide = function(element) { + this.resetMoveAndScale(element); + this.resetFadeOut(element); + }; + + + // return { + // fadeIn(element, duration) { + // element.style.transitionDuration = `${duration}ms`; + // element.classList.remove('hide'); + // element.classList.add('show'); + // console.log(this) + // }, + // resetFadeIn(element) { + // // element.style.show = null + // element.classList.remove('show'); + // element.classList.add('hide'); + // }, + // move(element, duration, translation) { + // element.style.transitionDuration = `${duration}ms`; + // element.style.transform = getTransform(translation, null); + // }, + // scale(element, duration, ratio) { + // element.style.transitionDuration = `${duration}ms`; + // element.style.transform = getTransform(null, ratio); + // }, + // fadeOut(element, duration){ + // element.style.transitionDuration = `${duration}ms`; + // element.classList.remove('show'); + // element.classList.add('hide'); + // }, + // resetFadeOut(element) { + // element.classList.remove('hide'); + // element.classList.add('show'); + // }, + // moveAndHide(element, duration, translation) { + // this.move(element, duration * 2 / 5, translation); + // this.fadeOut(element, duration * 3 / 5); + // }, + // showAndHide(element, duration){ + // animaster().fadeIn(element, duration / 3); + + // setTimeout(() => { + // animaster().fadeOut(element, duration / 3); + // }, duration / 3); + // }, + // heartBeating(element) { + // let timer = setInterval(() => { + // this.scale(element, 500, 1.4); + // setTimeout(() => { + // this.scale(element, 500, 1); + // }, 500); + // }, 1000); + // return { + // stop() { + // clearTimeout(timer); + // } + // } + // }, + // resetMoveAndScale(element) { + // this.move(element, 0, {x: 0, y: 0}); + // this.scale(element, 0, 1); + // }, + // resetMoveAndHide(element) { + // this.resetMoveAndScale(element); + // this.resetFadeOut(element); + // }, + // // addMove() { + // // this._steps++; + // // return this; + // // }, + // // play() { + + // // }, + // // _steps: [], + // } +} + diff --git a/styles.css b/styles.css index 68ad652..01c2a7f 100644 --- a/styles.css +++ b/styles.css @@ -33,7 +33,8 @@ height: 100px; padding: 5px; box-sizing: border-box; - background-color: #8d3f8d; + /* background-color: #8d3f8d; */ + background-color: #6ccf45; border: 2px solid #421456; color: white; transition-property: all;