Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,40 @@

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

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

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

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

```
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`:

```
element.style.заданныйАнимациейСтиль = null;
```

7. Сделай кнопку reset для анимации `moveAndHide` по аналогии с кнопкой stop из одного из предыдущих пунктов. При нажатии на кнопку reset последующие шаги анимации должны отменяться аналогично stop из `heartBeating`, а элемент должен мгновенно вернуться в исходное состояние с помощью функций из предыдущего пункта.
-7. Сделай кнопку reset для анимации `moveAndHide` по аналогии с кнопкой stop из одного из предыдущих пунктов. При нажатии на кнопку reset последующие шаги анимации должны отменяться аналогично stop из `heartBeating`, а элемент должен мгновенно вернуться в исходное состояние с помощью функций из предыдущего пункта.

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

Expand Down
34 changes: 33 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ <h3 class="animation-name">fadeIn</h3>
<h3 class="animation-name">move</h3>
<button class="button" id="movePlay">Play</button>
</header>
<div class="block" id="moveBlock"></div>
<div class="block show" id="moveBlock"></div>
</div>
<div class="container">
<header class="container-header">
Expand All @@ -27,6 +27,38 @@ <h3 class="animation-name">scale</h3>
</header>
<div class="block" id="scaleBlock"></div>
</div>
<div class="container">
<header class="container-header">
<h3 class="animation-name">move and hide</h3>
<button class="button" id="moveHidePlay">Play</button>
<button class="button" id="moveHideStop">Reset</button>
</header>
<div class="block show" id="moveHideBlock"></div>
</div>
<div class="container">
<header class="container-header">
<h3 class="animation-name">show and hide</h3>
<button class="button" id="showAndHidePlay">Play</button>
</header>
<div class="block hide" id="showAndHide"></div>
</div>
<div class="container">
<header class="container-header">
<h3 class="animation-name">heart beating</h3>
<button class="button" id="heartBeatingPlay">Play</button>
<button class="button" id="heartBeatingStop">Stop</button>
</header>
<div class="block show" id="heartBeating"></div>
</div>

<div class="container">
<header class="container-header">
<h3 class="animation-name">Невидимая анимация</h3>
<button class="button" id="myAnimPlay">Play</button>
</header>
<div class="block show" id="myAnim"></div>
</div>


<script src="index.js"></script>
</body>
Expand Down
177 changes: 150 additions & 27 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,188 @@
addListeners();
const animator = animaster();

function addListeners() {
document.getElementById('fadeInPlay')
.addEventListener('click', function () {
const block = document.getElementById('fadeInBlock');
fadeIn(block, 5000);
block.classList.contains('hide') ?
animator.addFadeIn(2000).play(block):
animator.addFadeOut(2000).play(block);
});

document.getElementById('movePlay')
.addEventListener('click', function () {
const block = document.getElementById('moveBlock');
move(block, 1000, {x: 100, y: 10});
animator.addMove(500, {x: 20, y:20}).play(block);
});

document.getElementById('scalePlay')
.addEventListener('click', function () {
const block = document.getElementById('scaleBlock');
scale(block, 1000, 1.25);
animator.addScale(1000,1.25).play(block);
});
document.getElementById('moveHidePlay')
.addEventListener('click', function () {
const block = document.getElementById('moveHideBlock');
animator.moveAndHide(block, 1000);
document
.getElementById("moveHideStop")
.addEventListener("click", function() {
animator.resetMoveAndScale(block);
animator.resetFadeOut(block);
});
});
document.getElementById('showAndHidePlay')
.addEventListener('click', function () {
const block = document.getElementById('showAndHide');
animator.showAndHide(block, 1000);
});
document.getElementById('heartBeatingPlay')
.addEventListener('click', function () {
const block = document.getElementById('heartBeating');
animator.fadeIn(block, 1000);
let heartBeatingStop = animator.heartBeating(block, 1000);
document
.getElementById("heartBeatingStop")
.addEventListener("click", heartBeatingStop.stop);

});
}
function animaster(){

this.steps = [];

/**
return{
/**
* Блок плавно появляется из прозрачного.
* @param element — HTMLElement, который надо анимировать
* @param duration — Продолжительность анимации в миллисекундах
* _
*/
function fadeIn(element, duration) {
element.style.transitionDuration = `${duration}ms`;
element.classList.remove('hide');
element.classList.add('show');
}

fadeIn(element, duration) {
element.style.transitionDuration = `${duration}ms`;
element.classList.remove('hide');
element.classList.add('show');
},

fadeOut(element,duration) {
element.style.transitionDuration = `${duration}ms`;
element.classList.remove('show');
element.classList.add('hide');
},

resetFadeIn(element) {
element.style.transitionDuration = null;
element.classList.remove('show');
element.classList.add('hide');
},

resetFadeOut(element) {
element.style.transitionDuration = null;
element.classList.remove('hide');
element.classList.add('show');
},

resetMoveAndScale(element) {
element.style.transitionDuration = null;
element.style.transform = null;
element.classList.remove('hide');
element.classList.add('show');
},

addMove(duration, translation) {
return this.addAnimation('move', duration, translation);
},

addScale(duration, ratio) {
return this.addAnimation('scale', duration, ratio);
},

addFadeIn(duration) {
return this.addAnimation('fadeIn', duration);
},

addFadeOut(duration) {
return this.addAnimation('fadeOut', duration);
},

play(element, cycled = false) {
let sum = 0;
for (let step of steps) {
setTimeout(
() => this[step.animation](element, step.duration, ...step.other),
sum
);
sum += step.duration;
}
steps=[];
},
addAnimation(animation, duration, ...other) {
steps.push({
animation,
duration,
other
});
return this;
},

/**
* Функция, передвигающая элемент
* @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);
}
move(element, duration, translation) {
element.style.transitionDuration = `${duration}ms`;
element.style.transform = getTransform(translation, null);
},

/**
moveAndHide(element,duration){
const timing = duration / 5;
animator.move(element, timing*2, { x: 100, y: 20 });
setTimeout(()=>animator.fadeOut(element,timing*3),timing * 2);
},
showAndHide(element,duration){
const timing = duration/3;
animator.fadeIn(element,timing*3);
setTimeout(timing*3)
setTimeout(()=>animator.fadeOut(element,timing*3),timing*3)
},
heartBeating(element,duration){
let beat = () => {
this.scale(element, duration / 2, 1.4);
setTimeout(() => this.scale(element, duration / 2, 1), duration / 2);
};
let beating = setInterval(beat, duration);
return {
stop() {
clearInterval(beating);
}
};

},


/**
* Функция, увеличивающая/уменьшающая элемент
* @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 getTransform(translation, ratio) {
const result = [];
if (translation) {
result.push(`translate(${translation.x}px,${translation.y}px)`);
scale(element, duration, ratio) {
element.style.transitionDuration = `${duration}ms`;
element.style.transform = getTransform(null, ratio);
},
}
if (ratio) {
result.push(`scale(${ratio})`);
function getTransform(translation, ratio) {
const result = [];
if (translation) {
result.push(`translate(${translation.x}px,${translation.y}px)`);
}
if (ratio) {
result.push(`scale(${ratio})`);
}
return result.join(' ');
}
return result.join(' ');
}
}