diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..b58b603 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/3-animaster.iml b/.idea/3-animaster.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/.idea/3-animaster.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..28a804d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..c104981 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/index.html b/index.html index 6546475..32dc5d5 100644 --- a/index.html +++ b/index.html @@ -6,28 +6,66 @@ -
-
-

fadeIn

- -
-
-
-
-
-

move

- -
-
-
-
-
-

scale

- -
-
-
- - +
+
+

Test

+
+
+
+
+
+

fadeIn

+ + +
+
+
+
+
+

move

+ + +
+
+
+
+
+

fadeOut

+ + +
+
+
+
+
+

moveAndHide

+ + +
+
+
+
+
+

showAndHide

+ +
+
+
+
+
+

heartBeating

+ + +
+
+
+
+
+

Flicker

+ +
+
+
+ \ No newline at end of file diff --git a/index.js b/index.js index 61e55f6..6087b42 100644 --- a/index.js +++ b/index.js @@ -1,56 +1,241 @@ -addListeners(); +class Animaster { + constructor(steps) { + if (steps) { + this._steps = steps.slice(); + } else { + this._steps = []; + } + } -function addListeners() { - document.getElementById('fadeInPlay') - .addEventListener('click', function () { - const block = document.getElementById('fadeInBlock'); - fadeIn(block, 5000); + scale(element, step) { + element.style.transitionDuration = `${step.duration}ms`; + element.style.transform = `${getTransform(null, step.scale)} ${element.style.transform}`; + } + + move(element, step) { + element.style.transitionDuration = `${step.duration}ms`; + element.style.transform = `${getTransform(step.translation, null)} ${element.style.transform}`; + } + + fadeIn(element, step) { + element.style.transitionDuration = `${step.duration}ms`; + element.classList.remove("hide"); + element.classList.add("show"); + } + + fadeOut(element, step) { + element.style.transitionDuration = `${step.duration}ms`; + element.classList.remove("show"); + element.classList.add("hide"); + } + + moveAndHide(element, step) { + this.move(element, {duration: 2 * step.duration / 5, translation: {x: 100, y: 20}}); + setTimeout(() => + this.fadeOut(element, {duration: 3 * step.duration / 5}), 2 * step.duration / 5); + } + + showAndHide(element, step) { + this.fadeIn(element, {duration: step.duration / 3}); + setTimeout(() => this.fadeOut(element, {duration: step.duration / 3}), step.duration / 3); + } + + heartBeating(element, step) { + this._id = setInterval(function () { + step.animaster.scale(element, {duration: 500, scale: 1.4}); + setTimeout(function () { + step.animaster.scale(element, {duration: 500, scale: 1}); + element.style.transform = ""; + }, 500); + }, 1500); + return { + stop: this.stopHeartBeating, + }; + } + + flicker(element, duration) { + element.style.duration = `${duration}ms`; + for (let i = 0X0; i < 0xffffff; i += 100) { + setTimeout(function () { + let str = i.toString(16); + str = str.padStart(6, "0"); + element.style.backgroundColor = `#${str}`; + }, 5); + } + } + + stopHeartBeating() { + clearInterval(this._id); + } + + addFlicker(duration) { + this._steps.push({ + animation: this.flicker, + duration: duration, + }); + return new Animaster(this._steps); + } + + addMove(duration, translation) { + this._steps.push({ + animation: this.move, + duration: duration, + translation: translation, }); + return new Animaster(this._steps); + } - document.getElementById('movePlay') - .addEventListener('click', function () { - const block = document.getElementById('moveBlock'); - move(block, 1000, {x: 100, y: 10}); + addScale(duration, scale) { + this._steps.push({ + animation: this.scale, + duration: duration, + scale: scale, }); + return new Animaster(this._steps); + } - document.getElementById('scalePlay') - .addEventListener('click', function () { - const block = document.getElementById('scaleBlock'); - scale(block, 1000, 1.25); + addMoveAndHide(duration, translation) { + this._steps.push({ + duration: duration, + translation: translation, + animation: this.moveAndHide, }); -} + return new Animaster(this._steps); + } -/** - * Блок плавно появляется из прозрачного. - * @param element — HTMLElement, который надо анимировать - * @param duration — Продолжительность анимации в миллисекундах - */ -function fadeIn(element, duration) { - element.style.transitionDuration = `${duration}ms`; - element.classList.remove('hide'); - element.classList.add('show'); -} + addShowAndHide(duration) { + this._steps.push({ + animation: this.showAndHide, + duration: duration, + }); + return new Animaster(this._steps); + } + + addHeartBeating() { + this._steps.push({ + animation: this.heartBeating, + animaster: this, + }); + return new Animaster(this._steps); + } + + addFadeOut(duration) { + this._steps.push({ + animation: this.fadeOut, + duration: duration, + }); + return new Animaster(this._steps); + } + + addFadeIn(duration) { + this._steps.push({ + animation: this.fadeIn, + duration: duration, + }); + return new Animaster(this._steps); + } + + play(element, cycled = false) { + const reset = function reset() { + element.style.opacity = opacity; + element.classList.remove("hide"); + element.classList.remove("show"); + element.style.transform = null; + element.style.scale = null; + }; + const opacity = element.style.opacity; + if (cycled) { + let delay = 0; + for (const step of this._steps) { + delay += step.duration; + } + const id = setInterval(() => { + this.playOnce(element); + reset(); + }, delay); + } else { + this.playOnce(element); + } + return { + stop: this.stopHeartBeating, + }; + } + + playOnce(element) { + let delay = 0; + for (const step of this._steps) { + setTimeout(() => step.animation.call(this, element, step), delay); + delay += step.duration; + } + return delay; + } -/** - * Функция, передвигающая элемент - * @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); + resetMoveOrScale(element) { + element.style.transform = ""; + element.transitionDuration = ""; + } + + resetFadeIn(element) { + element.style = null; + element.classList.remove("show"); + element.classList.add("hide"); + } + + + resetFadeOut(element) { + element.style = null; + element.classList.remove("hide"); + element.classList.add("show"); + } + + resetMoveAndHide(element) { + this.resetMoveOrScale(element); + this.resetFadeOut(element); + }; + + buildHandler() { + const animaster = this; + return function () { + animaster.play(this); + }; + } } +const anim = new 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); +const block = document.getElementById("testBlock") + .addEventListener("click", anim.buildHandler()); + +addListeners(); -/** - * Функция, увеличивающая/уменьшающая элемент - * @param element — HTMLElement, который надо анимировать - * @param duration — Продолжительность анимации в миллисекундах - * @param ratio — во сколько раз увеличить/уменьшить. Чтобы уменьшить, нужно передать значение меньше 1 - */ -function scale(element, duration, ratio) { - element.style.transitionDuration = `${duration}ms`; - element.style.transform = getTransform(null, ratio); +function addListener(name, option, func) { + document.querySelector(`#${name}${option}`) + .addEventListener("click", function () { + const block = document.querySelector(`#${name}Block`); + func(block); + }); +} +function addListeners() { + addListener("fadeIn", "Play", (block) => anim.fadeIn(block, {duration: 1000})); + addListener("move", "Play", (block) => anim.move(block, {duration: 1000, translation: {x: 100, y: 10}})); + addListener("scale", "Play", (block) => anim.scale(block, {duration: 1000, scale: 1.25})); + addListener("fadeOut", "Play", (block) => anim.fadeOut(block, {duration: 5000})); + addListener("moveAndHide", "Play", (block) => anim.moveAndHide(block, {duration: 5000})); + addListener("showAndHide", "Play", (block) => anim.showAndHide(block, {duration: 3000})); + addListener("heartBeating", "Play", (block) => anim.heartBeating(block, {animaster: anim})); + addListener("heartBeating", "Stop", (block) => anim.stopHeartBeating()); + addListener("moveAndHide", "Reset", (block) => anim.resetMoveAndHide(block)); + addListener("fadeIn", "Reset", (block) => anim.resetFadeIn(block)); + addListener("fadeOut", "Reset", (block) => anim.resetFadeOut(block)); + addListener("scale", "Reset", (block) => anim.resetMoveOrScale(block)); + addListener("move", "Reset", (block) => anim.resetMoveOrScale(block)); + addListener("changeColor", "Play", (block) => anim.flicker(block, 1000)); } function getTransform(translation, ratio) { @@ -61,5 +246,5 @@ function getTransform(translation, ratio) { if (ratio) { result.push(`scale(${ratio})`); } - return result.join(' '); + return result.join(" "); }