refactor 3-more into separate books

This commit is contained in:
Ilya Kantor 2015-02-27 13:21:58 +03:00
parent bd1d5e4305
commit 87639b2740
423 changed files with 9 additions and 9 deletions

View file

@ -0,0 +1,2 @@
Проще всего -- использовать функцию [](#animate), а еще удобнее -- `animateProp`.

View file

@ -0,0 +1,92 @@
/**
Docs: http://learn.javascript.ru/tutorial/lib
*/
function animate(opts) {
var start = new Date;
var delta = opts.delta || linear;
var timer = setInterval(function() {
var progress = (new Date - start) / opts.duration;
if (progress > 1) progress = 1;
opts.step( delta(progress) );
if (progress == 1) {
clearInterval(timer);
opts.complete && opts.complete();
}
}, opts.delay || 13);
return timer;
}
/**
Анимация стиля opts.prop у элемента opts.elem
от opts.from до opts.to продолжительностью opts.duration
в конце opts.complete
Например: animateProp({ elem: ..., prop: 'height', start:0, end: 100, duration: 1000 })
*/
function animateProp(opts) {
var start = opts.start, end = opts.end, prop = opts.prop;
opts.step = function(delta) {
var value = Math.round(start + (end - start)*delta);
opts.elem.style[prop] = value + 'px';
}
return animate(opts);
}
// ------------------ Delta ------------------
function elastic(progress) {
return Math.pow(2, 10 * (progress-1)) * Math.cos(20*Math.PI*1.5/3*progress);
}
function linear(progress) {
return progress;
}
function quad(progress) {
return Math.pow(progress, 2);
}
function quint(progress) {
return Math.pow(progress, 5);
}
function circ(progress) {
return 1 - Math.sin(Math.acos(progress));
}
function back(progress) {
return Math.pow(progress, 2) * ((1.5 + 1) * progress - 1.5);
}
function bounce(progress) {
for(var a = 0, b = 1, result; 1; a += b, b /= 2) {
if (progress >= (7 - 4 * a) / 11) {
return -Math.pow((11 - 6 * a - 11 * progress) / 4, 2) + Math.pow(b, 2);
}
}
}
function makeEaseInOut(delta) {
return function(progress) {
if (progress < .5)
return delta(2*progress) / 2;
else
return (2 - delta(2*(1-progress))) / 2;
}
}
function makeEaseOut(delta) {
return function(progress) {
return 1 - delta(1 - progress);
}
}

View file

@ -0,0 +1,87 @@
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="animate.js"></script>
</head>
<body>
<div class="carousel">
<a href="#" class="arrow left-arrow" id="prev">&#8249; </a>
<div class="gallery">
<ul id="images">
<li><img src="https://js.cx/carousel/1.png"></li>
<li><img src="https://js.cx/carousel/2.png"></li>
<li><img src="https://js.cx/carousel/3.png"></li>
<li><img src="https://js.cx/carousel/4.png"></li>
<li><img src="https://js.cx/carousel/5.png"></li>
<li><img src="https://js.cx/carousel/6.png"></li>
<li><img src="https://js.cx/carousel/7.png"></li>
<li><img src="https://js.cx/carousel/8.png"></li>
<li><img src="https://js.cx/carousel/9.png"></li>
<li><img src="https://js.cx/carousel/10.png"></li>
</ul>
</div>
<a href="#" class="arrow right-arrow" id="next">&#8250; </a>
</div>
<script>
/* этот код помечает картинки, для удобства разработки */
var lis = document.getElementsByTagName('li');
for(var i=0; i<lis.length; i++) {
lis[i].style.position='relative';
var span = document.createElement('span');
span.style.cssText='position:absolute;left:0;top:0';
span.innerHTML = i+1;
lis[i].appendChild(span);
}
/* конфигурация */
var width = 130; // ширина изображения
var count = 3; // количество изображений
var ul = document.getElementById('images');
var imgs = ul.getElementsByTagName('li');
var position = 0; // текущий сдвиг влево
document.getElementById('prev').onclick = function() {
if (position >= 0) return false; // уже прокручено до конца влево
// последнее передвижение влево может быть не на 3, а на 2 или 1 элемент
var newPosition = Math.min(position + width*count, 0);
animateProp({
elem: ul,
prop: "marginLeft",
start: position,
end: newPosition,
duration: 250,
delay: 20
});
position = newPosition;
return false;
}
document.getElementById('next').onclick = function() {
if (position <= -width*(imgs.length-count)) return false; // уже прокручено до конца вправо
// последнее передвижение вправо может быть не на 3, а на 2 или 1 элемент
var newPosition = Math.max(position-width*count, -width*(imgs.length-count));
animateProp({
elem: ul,
prop: "marginLeft",
start: position,
end: newPosition,
duration: 250,
delay: 20
});
position = newPosition;
return false;
};
</script>
</body>
</html>

View file

@ -0,0 +1,52 @@
body {
padding: 10px
}
.carousel {
position: relative;
width: 398px;
padding: 10px 40px;
border: 1px solid #CCC;
border-radius: 15px;
background: #eee;
}
.carousel img {
width: 130px;
height: 130px;
display: block; /* если не поставить block, в ряде браузеров будет inline -> лишнее пространтсво вокруг элементов */
}
.carousel .arrow {
position: absolute;
top: 57px;
padding: 3px 8px 8px 9px;
background: #ddd;
border-radius: 15px;
font-size: 24px;
color: #444;
text-decoration: none;
}
.carousel .arrow:hover {
background: #ccc;
}
.carousel .left-arrow {
left: 7px;
}
.carousel .right-arrow {
right: 7px;
}
.gallery {
width: 390px;
overflow: hidden;
}
.gallery ul {
height: 130px;
width: 9999px;
margin: 0;
padding: 0;
list-style: none;
}
.gallery ul li {
float: left;
}

View file

@ -0,0 +1,10 @@
# Анимируйте карусель
[importance 5]
Возьмите решение задачи [](/task/carousel) и сделайте передвижение карусели плавным, анимированым.
Подключите для этого файл <a href="/files/tutorial/js/animate.js">animate.js</a>.
Результат:
[iframe height=220 src="solution"]

View file

@ -0,0 +1,5 @@
Анимируйте одновременно свойства `left/top` и `width/height`.
Чтобы в процессе анимации таблица сохраняла геометрию -- создайте на месте `IMG` временный `DIV` фиксированного размера и переместите `IMG` внутрь него. После анимации можно вернуть как было.
[edit src="solution"]Открыть решение в песочнице[/edit]

View file

@ -0,0 +1,92 @@
/**
Docs: http://learn.javascript.ru/tutorial/lib
*/
function animate(opts) {
var start = new Date;
var delta = opts.delta || linear;
var timer = setInterval(function() {
var progress = (new Date - start) / opts.duration;
if (progress > 1) progress = 1;
opts.step( delta(progress) );
if (progress == 1) {
clearInterval(timer);
opts.complete && opts.complete();
}
}, opts.delay || 13);
return timer;
}
/**
Анимация стиля opts.prop у элемента opts.elem
от opts.from до opts.to продолжительностью opts.duration
в конце opts.complete
Например: animateProp({ elem: ..., prop: 'height', start:0, end: 100, duration: 1000 })
*/
function animateProp(opts) {
var start = opts.start, end = opts.end, prop = opts.prop;
opts.step = function(delta) {
var value = Math.round(start + (end - start)*delta);
opts.elem.style[prop] = value + 'px';
}
return animate(opts);
}
// ------------------ Delta ------------------
function elastic(progress) {
return Math.pow(2, 10 * (progress-1)) * Math.cos(20*Math.PI*1.5/3*progress);
}
function linear(progress) {
return progress;
}
function quad(progress) {
return Math.pow(progress, 2);
}
function quint(progress) {
return Math.pow(progress, 5);
}
function circ(progress) {
return 1 - Math.sin(Math.acos(progress));
}
function back(progress) {
return Math.pow(progress, 2) * ((1.5 + 1) * progress - 1.5);
}
function bounce(progress) {
for(var a = 0, b = 1, result; 1; a += b, b /= 2) {
if (progress >= (7 - 4 * a) / 11) {
return -Math.pow((11 - 6 * a - 11 * progress) / 4, 2) + Math.pow(b, 2);
}
}
}
function makeEaseInOut(delta) {
return function(progress) {
if (progress < .5)
return delta(2*progress) / 2;
else
return (2 - delta(2*(1-progress))) / 2;
}
}
function makeEaseOut(delta) {
return function(progress) {
return 1 - delta(1 - progress);
}
}

View file

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="animate.js"></script>
<style>img { display: block; cursor: pointer; }</style>
</head>
<body>
Кликните картинку для анимации. Расположение элементов при анимации не должно меняться!
<table>
<tr>
<td>Догнать</td>
<td><img onclick="growIn(this)" src="https://js.cx/clipart/flyjet.jpg" width="400" height="240">
</td>
<td>..и перегнать!</td>
</tr>
</table>
<script>
function growIn(img) {
var process = arguments.callee;
if (process.busy) return;
process.busy = true;
// переместить изображение в placeholder постоянного размера
var placeholder = document.createElement('div');
placeholder.style.width = img.offsetWidth + 'px';
placeholder.style.height = img.offsetHeight + 'px';
img.parentNode.replaceChild(placeholder, img);
placeholder.appendChild(img);
img.style.position='relative';
animateProp({ elem: img, prop: 'height', start:0, end: img.offsetHeight, duration: 3000 });
animateProp({ elem: img, prop: 'width', start:0, end: img.offsetWidth, duration: 3000 });
animateProp({ elem: img, prop: 'left', start:img.offsetWidth/2, end: 0, duration: 3000 });
animateProp({ elem: img, prop: 'top', start:img.offsetHeight/2, end: 0, duration: 3000, complete: done});
function done() {
placeholder.parentNode.replaceChild(img, placeholder);
img.style.position = '';
process.busy = false;
}
}
</script>
</body>
</html>

View file

@ -0,0 +1,92 @@
/**
Docs: http://learn.javascript.ru/tutorial/lib
*/
function animate(opts) {
var start = new Date;
var delta = opts.delta || linear;
var timer = setInterval(function() {
var progress = (new Date - start) / opts.duration;
if (progress > 1) progress = 1;
opts.step( delta(progress) );
if (progress == 1) {
clearInterval(timer);
opts.complete && opts.complete();
}
}, opts.delay || 13);
return timer;
}
/**
Анимация стиля opts.prop у элемента opts.elem
от opts.from до opts.to продолжительностью opts.duration
в конце opts.complete
Например: animateProp({ elem: ..., prop: 'height', start:0, end: 100, duration: 1000 })
*/
function animateProp(opts) {
var start = opts.start, end = opts.end, prop = opts.prop;
opts.step = function(delta) {
var value = Math.round(start + (end - start)*delta);
opts.elem.style[prop] = value + 'px';
}
return animate(opts);
}
// ------------------ Delta ------------------
function elastic(progress) {
return Math.pow(2, 10 * (progress-1)) * Math.cos(20*Math.PI*1.5/3*progress);
}
function linear(progress) {
return progress;
}
function quad(progress) {
return Math.pow(progress, 2);
}
function quint(progress) {
return Math.pow(progress, 5);
}
function circ(progress) {
return 1 - Math.sin(Math.acos(progress));
}
function back(progress) {
return Math.pow(progress, 2) * ((1.5 + 1) * progress - 1.5);
}
function bounce(progress) {
for(var a = 0, b = 1, result; 1; a += b, b /= 2) {
if (progress >= (7 - 4 * a) / 11) {
return -Math.pow((11 - 6 * a - 11 * progress) / 4, 2) + Math.pow(b, 2);
}
}
}
function makeEaseInOut(delta) {
return function(progress) {
if (progress < .5)
return delta(2*progress) / 2;
else
return (2 - delta(2*(1-progress))) / 2;
}
}
function makeEaseOut(delta) {
return function(progress) {
return 1 - delta(1 - progress);
}
}

View file

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="animate.js"></script>
<style>img { display: block; cursor: pointer; }</style>
</head>
<body>
Кликните картинку для анимации. Расположение элементов при анимации не должно меняться!
<table>
<tr>
<td>Догнать</td>
<td><img onclick="growIn(this)" src="https://js.cx/clipart/flyjet.jpg" width="400" height="240">
</td>
<td>..и перегнать!</td>
</tr>
</table>
<b>В процессе анимации повторные нажатия на изображение игнорируются.</b>
<script>
function growIn(img) {
/* ваш код */
}
</script>
</body>
</html>

View file

@ -0,0 +1,12 @@
# Анимировать лого
[importance 5]
Реализуйте анимацию, как в демке ниже (клик на картинку):
[iframe src="solution" border=1]
Продолжительность анимации: 3 секунды.
В процессе анимации пусть повторные клики на изображение игнорируются.

View file

@ -0,0 +1,27 @@
В HTML/CSS, падение мяча можно отобразить изменением свойства `ball.style.top` от 0 и до значения, соответствующего нижнему положению.
Нижняя граница элемента `field`, в котором находится мяч, имеет значение `field.clientHeight`. Но свойство `top` относится к верху мяча, поэтому оно меняется до `field.clientHeight - ball.clientHeight`.
Для создания анимационного эффекта лучше всего подойдет функция `bounce` в режиме `easeOut`.
Следующий код даст нам нужный результат:
```js
var img = document.getElementById('ball');
var field = document.getElementById('field');
img.onclick = function() {
var from = 0;
var to = field.clientHeight - img.clientHeight;
animate({
delay: 20,
duration: 1000,
*!*
delta: makeEaseOut(bounce),
step: function(delta) {
img.style.top = to*delta + 'px'
}
*/!*
});
}
```

View file

@ -0,0 +1,91 @@
/**
Docs: http://learn.javascript.ru/tutorial/lib
*/
function animate(opts) {
var start = new Date;
var delta = opts.delta || linear;
var timer = setInterval(function() {
var progress = (new Date - start) / opts.duration;
if (progress > 1) progress = 1;
opts.step( delta(progress) );
if (progress == 1) {
clearInterval(timer);
opts.complete && opts.complete();
}
}, opts.delay || 13);
return timer;
}
/**
Анимация стиля opts.prop у элемента opts.elem
от opts.from до opts.to продолжительностью opts.duration
в конце opts.complete
Например: animateProp({ elem: ..., prop: 'height', from:0, to: 100, duration: 1000 })
*/
function animateProp(opts) {
var start = opts.start, end = opts.end, prop = opts.prop;
opts.step = function(delta) {
opts.elem.style[prop] = Math.round(start + (start - end)*delta) + 'px';
}
return animate(opts);
}
// ------------------ Delta ------------------
function elastic(progress) {
return Math.pow(2, 10 * (progress-1)) * Math.cos(20*Math.PI*1.5/3*progress)
}
function linear(progress) {
return progress
}
function quad(progress) {
return Math.pow(progress, 2)
}
function quint(progress) {
return Math.pow(progress, 5)
}
function circ(progress) {
return 1 - Math.sin(Math.acos(progress))
}
function back(progress) {
return Math.pow(progress, 2) * ((1.5 + 1) * progress - 1.5)
}
function bounce(progress) {
for(var a = 0, b = 1, result; 1; a += b, b /= 2) {
if (progress >= (7 - 4 * a) / 11) {
return -Math.pow((11 - 6 * a - 11 * progress) / 4, 2) + Math.pow(b, 2);
}
}
}
function makeEaseInOut(delta) {
return function(progress) {
if (progress < .5)
return delta(2*progress) / 2
else
return (2 - delta(2*(1-progress))) / 2
}
}
function makeEaseOut(delta) {
return function(progress) {
return 1 - delta(1 - progress)
}
}

View file

@ -0,0 +1,50 @@
<!DOCTYPE HTML>
<html>
<head>
<script src="animate.js"></script>
<style>
#field {
height: 200px;
border-bottom: 3px black groove;
position: relative;
}
#ball {
position: absolute;
}
</style>
</head>
<body>
<div id="field">
<img src="https://js.cx/clipart/ball.svg" width="40" height="40" id="ball">
</div>
<script>
var img = document.getElementById('ball');
img.onclick = function() {
var to = document.getElementById('field').clientHeight - img.clientHeight;
animate({
delay: 20,
duration: 1000,
delta: makeEaseOut(bounce),
step: function(delta) {
img.style.top = to*delta + 'px'
}
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,91 @@
/**
Docs: http://learn.javascript.ru/tutorial/lib
*/
function animate(opts) {
var start = new Date;
var delta = opts.delta || linear;
var timer = setInterval(function() {
var progress = (new Date - start) / opts.duration;
if (progress > 1) progress = 1;
opts.step( delta(progress) );
if (progress == 1) {
clearInterval(timer);
opts.complete && opts.complete();
}
}, opts.delay || 13);
return timer;
}
/**
Анимация стиля opts.prop у элемента opts.elem
от opts.from до opts.to продолжительностью opts.duration
в конце opts.complete
Например: animateProp({ elem: ..., prop: 'height', from:0, to: 100, duration: 1000 })
*/
function animateProp(opts) {
var start = opts.start, end = opts.end, prop = opts.prop;
opts.step = function(delta) {
opts.elem.style[prop] = Math.round(start + (start - end)*delta) + 'px';
}
return animate(opts);
}
// ------------------ Delta ------------------
function elastic(progress) {
return Math.pow(2, 10 * (progress-1)) * Math.cos(20*Math.PI*1.5/3*progress)
}
function linear(progress) {
return progress
}
function quad(progress) {
return Math.pow(progress, 2)
}
function quint(progress) {
return Math.pow(progress, 5)
}
function circ(progress) {
return 1 - Math.sin(Math.acos(progress))
}
function back(progress) {
return Math.pow(progress, 2) * ((1.5 + 1) * progress - 1.5)
}
function bounce(progress) {
for(var a = 0, b = 1, result; 1; a += b, b /= 2) {
if (progress >= (7 - 4 * a) / 11) {
return -Math.pow((11 - 6 * a - 11 * progress) / 4, 2) + Math.pow(b, 2);
}
}
}
function makeEaseInOut(delta) {
return function(progress) {
if (progress < .5)
return delta(2*progress) / 2
else
return (2 - delta(2*(1-progress))) / 2
}
}
function makeEaseOut(delta) {
return function(progress) {
return 1 - delta(1 - progress)
}
}

View file

@ -0,0 +1,22 @@
<!DOCTYPE HTML>
<html>
<head>
<script src="animate.js"></script>
<style>
#field {
height: 200px;
border-bottom: 1px solid black;
}
</style>
</head>
<body>
<div id="field">
<img src="https://js.cx/clipart/ball.svg" width="40" height="40" id="ball">
</div>
</body>
</html>

View file

@ -0,0 +1,10 @@
# Анимируйте мяч
[importance 5]
Сделайте так, чтобы мяч подпрыгивал. Кликните по мячу, чтобы увидеть, как это должно выглядеть.
[iframe height=250 src="solution"]
В исходный документ включена функция [](#animate) и набор `delta`-функций.

View file

@ -0,0 +1,35 @@
Посмотрите задачу [](/task/animate-ball). Там создаётся подпрыгивающий мяч. А для решения этой задачи нам нужно добавить еще одну анимацию для `elem.style.left`.
Горизонтальная координата меняется по другому закону, нежели вертикальная. Она не "подпрыгивает", а постоянно увеличивается, постепенно сдвигая мяч вправо.
Мы могли бы применить для неё `linear`, но тогда горизонтальное движение будет отставать от скачков мяча. Более красиво будет что-то типа `makeEaseOut(quad)`.
Код:
```js
img.onclick = function() {
var height = document.getElementById('field').clientHeight - img.clientHeight
var width = 100
animate({
delay: 20,
duration: 1000,
delta: makeEaseOut(bounce),
step: function(delta) {
img.style.top = height*delta + 'px'
}
});
*!*
animate({
delay: 20,
duration: 1000,
delta: makeEaseOut(quad),
step: function(delta) {
img.style.left = width*delta + "px"
}
});
*/!*
}
```

View file

@ -0,0 +1,91 @@
/**
Docs: http://learn.javascript.ru/tutorial/lib
*/
function animate(opts) {
var start = new Date;
var delta = opts.delta || linear;
var timer = setInterval(function() {
var progress = (new Date - start) / opts.duration;
if (progress > 1) progress = 1;
opts.step( delta(progress) );
if (progress == 1) {
clearInterval(timer);
opts.complete && opts.complete();
}
}, opts.delay || 13);
return timer;
}
/**
Анимация стиля opts.prop у элемента opts.elem
от opts.from до opts.to продолжительностью opts.duration
в конце opts.complete
Например: animateProp({ elem: ..., prop: 'height', from:0, to: 100, duration: 1000 })
*/
function animateProp(opts) {
var start = opts.start, end = opts.end, prop = opts.prop;
opts.step = function(delta) {
opts.elem.style[prop] = Math.round(start + (start - end)*delta) + 'px';
}
return animate(opts);
}
// ------------------ Delta ------------------
function elastic(progress) {
return Math.pow(2, 10 * (progress-1)) * Math.cos(20*Math.PI*1.5/3*progress)
}
function linear(progress) {
return progress
}
function quad(progress) {
return Math.pow(progress, 2)
}
function quint(progress) {
return Math.pow(progress, 5)
}
function circ(progress) {
return 1 - Math.sin(Math.acos(progress))
}
function back(progress) {
return Math.pow(progress, 2) * ((1.5 + 1) * progress - 1.5)
}
function bounce(progress) {
for(var a = 0, b = 1, result; 1; a += b, b /= 2) {
if (progress >= (7 - 4 * a) / 11) {
return -Math.pow((11 - 6 * a - 11 * progress) / 4, 2) + Math.pow(b, 2);
}
}
}
function makeEaseInOut(delta) {
return function(progress) {
if (progress < .5)
return delta(2*progress) / 2
else
return (2 - delta(2*(1-progress))) / 2
}
}
function makeEaseOut(delta) {
return function(progress) {
return 1 - delta(1 - progress)
}
}

View file

@ -0,0 +1,58 @@
<!DOCTYPE HTML>
<html>
<head>
<script src="animate.js"></script>
<style>
#field {
height: 200px;
border-bottom: 3px black groove;
position: relative;
}
#ball {
position: absolute;
}
</style>
</head>
<body>
<div id="field">
<img src="https://js.cx/clipart/ball.svg" width="40" height="40" id="ball">
</div>
<script>
var img = document.getElementById('ball');
img.onclick = function() {
var height = document.getElementById('field').clientHeight - img.clientHeight;
var width = 100;
animate({
delay: 20,
duration: 1000,
delta: makeEaseOut(bounce),
step: function(delta) {
img.style.top = height*delta + 'px'
}
});
animate({
delay: 20,
duration: 1000,
delta: makeEaseOut(quad),
step: function(delta) {
img.style.left = width*delta + "px"
}
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,91 @@
/**
Docs: http://learn.javascript.ru/tutorial/lib
*/
function animate(opts) {
var start = new Date;
var delta = opts.delta || linear;
var timer = setInterval(function() {
var progress = (new Date - start) / opts.duration;
if (progress > 1) progress = 1;
opts.step( delta(progress) );
if (progress == 1) {
clearInterval(timer);
opts.complete && opts.complete();
}
}, opts.delay || 13);
return timer;
}
/**
Анимация стиля opts.prop у элемента opts.elem
от opts.from до opts.to продолжительностью opts.duration
в конце opts.complete
Например: animateProp({ elem: ..., prop: 'height', from:0, to: 100, duration: 1000 })
*/
function animateProp(opts) {
var start = opts.start, end = opts.end, prop = opts.prop;
opts.step = function(delta) {
opts.elem.style[prop] = Math.round(start + (start - end)*delta) + 'px';
}
return animate(opts);
}
// ------------------ Delta ------------------
function elastic(progress) {
return Math.pow(2, 10 * (progress-1)) * Math.cos(20*Math.PI*1.5/3*progress)
}
function linear(progress) {
return progress
}
function quad(progress) {
return Math.pow(progress, 2)
}
function quint(progress) {
return Math.pow(progress, 5)
}
function circ(progress) {
return 1 - Math.sin(Math.acos(progress))
}
function back(progress) {
return Math.pow(progress, 2) * ((1.5 + 1) * progress - 1.5)
}
function bounce(progress) {
for(var a = 0, b = 1, result; 1; a += b, b /= 2) {
if (progress >= (7 - 4 * a) / 11) {
return -Math.pow((11 - 6 * a - 11 * progress) / 4, 2) + Math.pow(b, 2);
}
}
}
function makeEaseInOut(delta) {
return function(progress) {
if (progress < .5)
return delta(2*progress) / 2
else
return (2 - delta(2*(1-progress))) / 2
}
}
function makeEaseOut(delta) {
return function(progress) {
return 1 - delta(1 - progress)
}
}

View file

@ -0,0 +1,22 @@
<!DOCTYPE HTML>
<html>
<head>
<script src="animate.js"></script>
<style>
#field {
height: 200px;
border-bottom: 1px solid black;
}
</style>
</head>
<body>
<div id="field">
<img src="https://js.cx/clipart/ball.svg" width="40" height="40" id="ball">
</div>
</body>
</html>

View file

@ -0,0 +1,11 @@
# Анимируйте падение мяча с отскоками вправо
[importance 5]
Заставьте мяч падать вправо. Кликните, чтобы увидеть в действии.
[iframe height=250 src="solution"]
Напишите код, который будет анимировать мяч. Дистанция вправо составляет `100px`.
В исходный документ включена функция [](#animate) и набор `delta`-функций.

View file

@ -0,0 +1,697 @@
# JS-Анимация
В этой главе мы рассмотрим устройство браузерной анимации. Она примерно одинаково реализована во всех фреймворках.
Понимание этого позволит разобраться в происходящем, если что-то вдруг не работает, а также написать сложную анимацию самому.
Анимация при помощи JavaScript и современная CSS-анимация дополняют друг друга.
[cut]
## Основы анимации
С точки зрения HTML/CSS, анимация -- это постепенное изменение стиля DOM-элемента. Например, увеличение координаты `style.left` от `0px` до `100px` сдвигает элемент.
Код, который производит изменение, вызывается таймером. Интервал таймера очень мал и поэтому анимация выглядит плавной. Это тот же принцип, что и в кино: для непрерывной анимации достаточно 24 или больше вызовов таймера в секунду.
Псевдо-код для анимации выглядит так:
```js
var timer = setInterval(function() {
показать новый кадр
if (время вышло) clearInterval(timer);
}, 10)
```
Задержка между кадрами в данном случае составляет `10 ms`, что означает `100` кадров в секунду.
В большинстве фреймворков, задержка по умолчанию составляет `10`-`15` мс. Меньшая задержка делает анимацию более плавной, но только в том случае, если браузер достаточно быстр, чтобы анимировать каждый шаг вовремя.
Если анимация требует большого количества вычислений, то нагрузка процессора может доходить до 100% и вызывать ощутимые "тормоза" в работе браузера. В
таком случае, задержку можно увеличить. Например, 40мс дадут нам 25 кадров в секунду, что очень близко к кинематографическому стандарту в 24 кадра.
[smart header="`setInterval` вместо `setTimeout`"]
Мы используем `setInterval`, а не рекурсивный `setTimeout`, потому что нам нужен *один кадр за промежуток времени*, а не *фиксированная задержка между кадрами*</b>.
В статье [](/setTimeout-setInterval) описана разница между `setInterval` и рекурсивным `setTimeout`.
[/smart]
### Пример
Например, передвинем элемент путём изменения `element.style.left` от 0 до 100px. Изменение происходит на 1px каждые 10мс.
```html
<script>
function move(elem) {
var left = 0; // начальное значение
function frame() { // функция для отрисовки
left++;
elem.style.left = left + 'px'
if (left == 100) {
clearInterval(timer); // завершить анимацию
}
}
var timer = setInterval(frame, 10) // рисовать каждые 10мс
}
</script>
<div onclick="move(this.children[0])" class="example_path">
<div class="example_block"></div>
</div>
```
Кликните для демонстрации:
[iframe height=60 src="move100" link]
## Структура анимации
У анимации есть три основных параметра:
<dl>
<dt>`delay`</dt>
<dd>Время между кадрами (в миллисекундах, т.е. 1/1000 секунды). Например, 10мс.</dd>
<dt>`duration`</dt>
<dd>Общее время, которое должна длиться анимация, в мс. Например, 1000мс.</dd>
<dt>`step(progress)`</dt>
<dd>Функция **`step(progress)`** занимается отрисовкой состояния анимации, соответствующего времени `progress`.</dd>
</dl>
Каждый кадр выполняется, сколько времени прошло: `progress = (now-start)/duration`. Значение `progress` меняется от `0` в начале анимации до `1` в конце. Так как вычисления с дробными числами не всегда точны, то в конце оно может быть даже немного больше 1. В этом случае мы уменьшаем его до 1 и завершаем анимацию.
Создадим функцию `animate`, которая получает объект со свойствами `delay, duration, step` и выполняет анимацию.
```js
function animate(opts) {
var start = new Date; // сохранить время начала
var timer = setInterval(function() {
// вычислить сколько времени прошло
var progress = (new Date - start) / opts.duration;
if (progress > 1) progress = 1;
// отрисовать анимацию
opts.step(progress);
if (progress == 1) clearInterval(timer); // конец :)
}, opts.delay || 10); // по умолчанию кадр каждые 10мс
}
```
### Пример
Анимируем ширину элемента `width` от `0` до `100%`, используя нашу функцию:
```js
function stretch(elem) {
animate({
duration: 1000, // время на анимацию 1000 мс
step: function(progress) {
elem.style.width = progress*100 + '%';
}
});
}
```
Кликните для демонстрации:
[iframe height=60 src="width" link]
Функция `step` может получать дополнительные параметры анимации из `opts` (через `this`) или через замыкание.
Следующий пример использует параметр `to` из замыкания для анимации бегунка:
```js
function move(elem) {
var to = 500;
animate({
duration: 1000,
step: function(progress) {
// progress меняется от 0 до 1, left от 0px до 500px
elem.style.left = to*progress + "px";
}
});
}
```
Кликните для демонстрации:
[iframe height=60 src="move" link]
## Временная функция delta
В сложных анимациях свойства изменяются по определённому закону. Зачастую, он гораздо сложнее, чем простое равномерное возрастание/убывание.
Для того, чтобы можно было задать более хитрые виды анимации, в алгоритм добавляется дополнительная функция `delta(progress)`, которая вычисляет текущее состояние анимации от 0 до 1, а `step` использует её значение вместо `progress`.
В `animate` изменится всего одна строчка. Было:
```js
...
opts.step(progress);
...
```
Станет:
```js
...
opts.step( opts.delta(progress) );
...
```
```js
//+ hide="Раскрыть код animate с delta"
function animate(opts) {
var start = new Date;
var timer = setInterval(function() {
var progress = (new Date - start) / opts.duration;
if (progress > 1) progress = 1;
opts.step( opts.delta(progress) );
if (progress == 1) clearInterval(timer);
}, opts.delay || 10);
}
```
Такое небольшое изменение добавляет много гибкости. Функция `step` занимается всего лишь отрисовкой текущего состояния анимации, а само состояние по времени определяется в `delta`.
Разные значения `delta` заставляют скорость анимации, ускорение и другие параметры вести себя абсолютно по-разному.
Рассмотрим примеры анимации движения с использованием различных `delta`.
### Линейная delta
Самая простая функция `delta` -- это та, которая просто возвращает `progress`.
```js
function linear(progress) {
return progress;
}
```
То есть, как будто никакой `delta` нет. Состояние анимации (которое при передвижении отображается как координата `left`) зависит от времени линейно.
**График:**
<img src="linear.svg">
**По горизонтали - `progress`, а по вертикали - `delta(progress)`.**
Пример:
```html
<div onclick="move(this.children[0], linear)" class="example_path">
<div class="example_block"></div>
</div>
```
Здесь и далее функция `move` будет такой:
```js
function move(elem, delta, duration) {
var to = 500;
animate({
delay: 10,
duration: duration || 1000,
delta: delta,
step: function(delta) {
elem.style.left = to*delta + "px"
}
});
}
```
То есть, она будет перемещать бегунок, изменяя `left` по закону `delta`, за `duration` мс (по умолчанию 1000мс).
Кликните для демонстрации линейной `delta`:
<div onclick="move(this.children[0], linear)" class="example_path">
<div class="example_block"></div>
</div>
### В степени n
Вот еще один простой случай. `delta` - это `progress` в `n-й` степени . Частные случаи - квадратичная, кубическая функции и т.д.
Для квадратичной функции:
```js
function quad(progress) {
return Math.pow(progress, 2)
}
```
**График квадратичной функции:**
<img src="quad.svg">
Пример для квадратичной функции (клик для просмотра):
<div onclick="move(this.children[0], quad)" class="example_path">
<div class="example_block"></div>
</div>
Увеличение степени влияет на ускорение. Например, график для 5-й степени:
<img src="quint.svg">
И пример:
<div onclick="move(this.children[0], quint)" class="example_path">
<div class="example_block"></div>
</div>
**Функция `delta` описывает развитие анимации в зависимости от времени.**
В примере выше -- сначала медленно: время идёт (ось X), а состояние анимации почти не меняется (ось Y), а потом всё быстрее и быстрее. Другие графики зададут иное поведение.
### Дуга
Функция:
```js
function circ(progress) {
return 1 - Math.sin(Math.acos(progress))
}
```
**График:**
<img src="circ.svg">
Пример:
<div onclick="move(this.children[0], circ)" class="example_path">
<div class="example_block"></div>
</div>
### Back: стреляем из лука
Эта функция работает по принципу лука: сначала мы "натягиваем тетиву", а затем "стреляем".
В отличие от предыдущих функций, эта зависит от дополнительного параметра `x`, который является "коэффициентом упругости". Он определяет расстояние, на которое "оттягивается тетива".
Её код:
```js
function back(progress, x) {
return Math.pow(progress, 2) * ((x + 1) * progress - x)
}
```
**График для `x = 1.5`:**
<img src="back.svg">
Пример для `x = 1.5`:
<div onclick="move(this.children[0], back)" class="example_path">
<div class="example_block"></div>
</div>
### Отскок
Представьте, что мы отпускаем мяч, он падает на пол, несколько раз отскакивает и останавливается.
Функция `bounce` делает то же самое, только наоборот: "подпрыгивание" начинается сразу.
Эта функция немного сложнее предыдущих и использует специальные коэффициенты:
```js
function bounce(progress) {
for (var a = 0, b = 1, result; 1; a += b, b /= 2) {
if (progress >= (7 - 4 * a) / 11) {
return -Math.pow((11 - 6 * a - 11 * progress) / 4, 2) + Math.pow(b, 2)
}
}
}
```
Код взят из MooTools.FX.Transitions. Конечно же, есть и другие реализации `bounce`.
Пример:
<div onclick="move(this.children[0], bounce, 2000)" class="example_path">
<div class="example_block"></div>
</div>
### Упругая анимация
Эта функция зависит от дополнительного параметра `x`, который определяет начальный диапазон.
```js
function elastic(progress, x) {
return Math.pow(2, 10 * (progress-1)) * Math.cos(20*Math.PI*x/3*progress)
}
```
**График для `x=1.5`:**
<img src="elastic.svg">
Пример для `x=1.5`:
<div onclick="move(this.children[0], elastic, 2000)" class="example_path">
<div class="example_block"></div>
</div>
## Реверсивные функции (easeIn, easeOut, easeInOut)
Обычно, JavaScript-фреймворк предоставляет несколько `delta`-функций.
Их прямое использование называется "easeIn".
**Иногда нужно показать анимацию в обратном режиме. Преобразование функции, которое даёт такой эффект, называется "easeOut"**.
### easeOut
В режиме "easeOut", значение delta вычисляется так:
`deltaEaseOut(progress) = 1 - delta(1 - progress)`
Например, функция `bounce` в режиме "easeOut":
```js
function bounce(progress) {
for (var a = 0, b = 1, result; 1; a += b, b /= 2) {
if (progress >= (7 - 4 * a) / 11) {
return -Math.pow((11 - 6 * a - 11 * progress) / 4, 2) + Math.pow(b, 2);
}
}
}
*!*
function makeEaseOut(delta) { // преобразовать delta
return function(progress) {
return 1 - delta(1 - progress);
}
}
*/!*
*!*var bounceEaseOut = makeEaseOut(bounce);*/!*
```
Кликните для демонстрации:
<div onclick="move(this.children[0], makeEaseOut(bounce))" class="example_path">
<div class="example_block"></div>
</div>
Давайте посмотрим, как преобразование `easeOut` изменяет поведение функции:
<img src="bounce-inout.svg">
Красным цветом обозначен <span style="color:red">easeIn</span>, а зеленым - <span style="color:#0f0">easeOut</span>.
<ul>
<li><span style="color:red">Обычно</span> анимируемый объект сначала медленно скачет внизу, а затем, в конце, резко достигает верха..</li>
<li>А после <span style="color:red">easeOut</span> он сначала прыгает наверх, а затем медленно скачет внизу.</li>
</ul>
**При `easeOut` анимация развивается в обратном временном порядке.**
Если есть анимационный эффект, такой как подпрыгивание -- он будет показан в конце, а не в начале (или наоборот, в начале, а не в конце).
### easeInOut
А еще можно сделать так, чтобы показать эффект *и* в начале *и* в конце анимации. Соответствующее преобразование называется "easeInOut".
Его код выглядит так:
```js
if (progress <= 0.5) { // первая половина анимации)
return delta(2 * progress) / 2;
} else { // вторая половина
return (2 - delta(2 * (1 - progress))) / 2;
}
```
Например, `easeInOut` для `bounce`:
<div onclick="move(this.children[0], makeEaseInOut(bounce), 3000)" class="example_path">
<div class="example_block"></div>
</div>
*У этого примера длительность составляет 3 секунды для того, что бы хватило времени для обоих эффектов(начального и конечного).*
Код, который трансформирует `delta`:
```js
function makeEaseInOut(delta) {
return function(progress) {
if (progress < .5)
return delta(2*progress) / 2;
else
return (2 - delta(2*(1-progress))) / 2;
}
}
bounceEaseInOut = makeEaseInOut(bounce);
```
Трансформация "easeInOut" объединяет в себе два графика в один: `easeIn` для первой половины анимации и `easeOut` -- для второй.
Например, давайте посмотрим эффект <span style="color:#0f0">`easeOut`</span>/<span style="color:#00f">`easeInOut`</span> на примере функции `circ`:
<img src="circ-ease.svg">
Как видно, график первой половины анимации представляет собой уменьшенный "easeIn", а второй -- уменьшенный "easeOut". В результате, анимация начинается и заканчивается одинаковым эффектом.
### Графопостроитель
Для наглядной демонстрации в действии различных delta, как нормальных(easeIn), так и измененных(easeOut,easeInOut), я подготовил графопостроитель.
<iframe src="/files/tutorial/browser/animation/plot.html" style="border:1px;height:460px;width:600px"></iframe>
<a href="/files/tutorial/browser/animation/plot.html">Открыть в новом окне</a>.
Выберите функцию и нажмите `Рисовать!`
<ul>
<li><span style="color:#f00">easeIn</span> - базовое поведение: медленная анимация в начале, с постепенным ускорением.</li>
<li><span style="color:#0f0">easeOut</span> - поведение, обратное <span style="color:#f00">easeIn</span>: быстрая анимация на старте, а затем все медленней и медленней.</li>
<li><span style="color:#00f">easeInOut</span> - слияние обоих поведений. Анимация разделяется на две части. Первая часть - это `easeIn`, а вторая - `easeOut`.</li>
</ul>
Для примера, попробуйте "bounce".
[summary]
Процесс анимации полностью в ваших руках благодаря `delta`. Вы можете сделать ее настолько реалистичной, насколько захотите.
И кстати. Если вы когда-нибудь изучали математику... Некоторые вещи все же бывают полезны в жизни :) Можно продумать и сделать красиво.
Впрочем, исходя из практики, можно сказать, что варианты `delta`, описанные выше, покрывают 95% потребностей в анимации.
[/summary]
## Сложные варианты step
Анимировать можно все, что угодно. Вместо движения, как во всех предыдущих примерах, вы можете изменять прозрачность, ширину, высоту, цвет... Все, о чем вы можете подумать!
Достаточно лишь написать соответствующий `step`.
### Подсветка цветом
Функция `highlight`, представленная ниже, анимирует изменение цвета.
```js
function highlight(elem) {
var from = [255,0,0], to = [255,255,255]
animate({
delay: 10,
duration: 1000,
delta: linear,
step: function(delta) {
elem.style.backgroundColor = 'rgb(' +
Math.max(Math.min(parseInt((delta * (to[0]-from[0])) + from[0], 10), 255), 0) + ',' +
Math.max(Math.min(parseInt((delta * (to[1]-from[1])) + from[1], 10), 255), 0) + ',' +
Math.max(Math.min(parseInt((delta * (to[2]-from[2])) + from[2], 10), 255), 0) + ')'
}
})
}
```
<div onclick="highlight(this, linear)" style="font-size:150%">Кликните по этой надписи, чтобы увидеть функцию в действии</div>
А теперь тоже самое, но `delta = makeEaseOut(bounce)`:
<div onclick="highlight(this, makeEaseOut(bounce))" style="font-size:150%">Кликните по этой надписи, чтобы увидеть функцию в действии</div>
### Набор текста
Вы можете создавать интересные анимации, как, например, набор текста в "скачущем" режиме:
[pre]
<textarea id="textExample" style="border: 1px solid #BBB; color:#444" rows="4" cols="60">Он стал под дерево и ждет.
И вдруг граахнул гром —
Летит ужасный Бармаглот
И пылкает огнем!
</textarea>
<button onclick="animateText(document.getElementById('textExample'))">Запустить анимированную печать!</button>
[/pre]
Исходный код:
```js
function animateText(textArea) {
var text = textArea.value
var to = text.length, from = 0
animate({
delay: 20,
duration: 5000,
delta: bounce,
step: function(delta) {
var result = (to-from) * delta + from
textArea.value = text.substr(0, Math.ceil(result))
}
})
}
```
## Итого [#animate]
Анимация выполняется путём использования `setInterval` с маленькой задержкой, порядка 10-50мс. При каждом запуске происходит отрисовка очередного кадра.
Анимационная функция, немного расширенная:
```js
function animate(opts) {
var start = new Date;
var delta = opts.delta || linear;
var timer = setInterval(function() {
var progress = (new Date - start) / opts.duration;
if (progress > 1) progress = 1;
opts.step( delta(progress) );
if (progress == 1) {
clearInterval(timer);
opts.complete && opts.complete();
}
}, opts.delay || 13);
return timer;
}
```
Основные параметры:
<ul>
<li>`delay` - задержка между кадрами, по умолчанию 13мс.</li>
<li>`duration` - длительность анимации в мс.</li>
<li>`delta` - функция, которая определяет состояние анимации каждый кадр. Получает часть времени от 0 до 1, возвращает завершенность анимации от 0 до 1. По умолчанию `linear`.</li>
<li>`step` - функция, которая отрисовывает состояние анимации от 0 до 1.</li>
<li>`complete` - функция для вызова после завершенности анимации.</li>
<li>Вызов `animate` возвращает таймер, чтобы анимацию можно было отменить.</li>
</ul>
Функцию `delta` можно модифицировать, используя трансформации `easeOut/easeInOut`:
```js
function makeEaseInOut(delta) {
return function(progress) {
if (progress < .5) return delta(2*progress) / 2;
else return (2 - delta(2*(1-progress))); / 2;
}
}
function makeEaseOut(delta) {
return function(progress) {
return 1 - delta(1 - progress);
}
}
```
На основе этой общей анимационной функции можно делать и более специализированные, например `animateProp`, которая анимирует свойство `opts.elem[opts.prop]` от `opts.start px` до `opts.end px` :
```js
//+ run
function animateProp(opts) {
var start = opts.start, end = opts.end, prop = opts.prop;
opts.step = function(delta) {
opts.elem.style[prop] = Math.round(start + (end - start)*delta) + 'px';
}
return animate(opts);
}
// Использование:
animateProp({
elem: document.body,
prop: "width",
start: 0,
duration: 2000,
end: document.body.clientWidth
});
```
Можно добавить еще варианты `delta`, `step`, создать общий фреймворк для анимации с единым таймером и т.п. Собственно, это и делают библиотеки типа jQuery.
### Советы по оптимизации
<dl>
<dt>Большое количество таймеров сильно нагружают процессор.</dt>
<dd>Если вы хотите запустить несколько анимаций одновременно, например, показать много падающих снежинок, то управляйте ими с помощью одного таймера.
Дело в том, что каждый таймер вызывает перерисовку. Поэтому браузер работает гораздо эффективней, если для всех анимаций приходится делать одну объединенную перерисовку вместо нескольких.
Фреймворки обычно используют один `setInterval` и запускают все кадры в заданном интервале.
</dd>
<dt>Помогайте браузеру в отрисовке</dt>
<dd>Браузер управляет отрисовкой дерева и элементы зависят друг от друга.
Если анимируемый элемент лежит глубоко в DOM, то другие элементы зависят от его размеров и позиции. Даже если анимация не касается их, браузер все равно делает лишние расчёты.
Для того, чтобы анимация меньше расходовала ресурсы процессора(и была плавнее), не анимируйте элемент, находящийся глубоко в DOM.
Вместо этого:
<ol>
<li>Для начала, удалите анимируемый элемент из DOM и прикрепите его непосредственно к `BODY`. Вам, возможно придется использовать `position: absolute` и выставить координаты.</li>
<li>Анимируйте элемент.</li>
<li>Верните его обратно в DOM.
</ol>
Эта хитрость поможет выполнять сложные анимации и при этом экономить ресурсы процессора.
</dd>
</dl>
Там, где это возможно, стоит использовать CSS-анимацию, особенно на смартфонах и планшетах, где процессор слабоват и JavaScript работает не быстро.
[head]
<link type="text/css" rel="stylesheet" href="/files/tutorial/browser/animation/animate.css" />
<script src="/files/tutorial/js/animate.js"></script>
<script src="/files/tutorial/browser/animation/step.js"></script>
<script>
function move(elem, delta, duration) {
var to = 500;
animate({
delay: 10,
duration: duration || 1000,
delta: delta,
step: function(delta) {
elem.style.left = to*delta + "px"
}
});
}
</script>
[/head]

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="234px" height="240px" viewBox="0 0 234 240" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: bin/sketchtool 1.3 (252) - http://www.bohemiancoding.com/sketch -->
<title>back.svg</title>
<desc>Created with bin/sketchtool.</desc>
<defs></defs>
<g id="combined" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="back.svg" sketch:type="MSArtboardGroup">
<path d="M34,209.5 L34,22.1600037" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M34,22.5 C32.95,26.28 32.05,29.52 31,33.3 C33.1,33.3 34.9,33.3 37,33.3 C35.95,29.52 35.05,26.28 34,22.5 C34,22.5 34,22.5 34,22.5 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M24.5,194 L208.509995,194" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M208.5,194 C204.72,192.95 201.48,192.05 197.7,191 C197.7,193.1 197.7,194.9 197.7,197 C201.48,195.95 204.72,195.05 208.5,194 C208.5,194 208.5,194 208.5,194 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M35.3289777,193.635841 C35.3289777,193.635841 82.5458318,209.484914 105.066994,208.643536 C127.588155,207.802158 166.326582,214.914724 208.465749,22.4456533" id="Path-747" stroke="#EE6B47" stroke-width="3" sketch:type="MSShapeGroup"></path>
<text id="0" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="212">0</tspan>
</text>
<text id="1" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="36">1</tspan>
</text>
<text id="-2" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="200" y="212">1</tspan>
</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="234px" height="240px" viewBox="0 0 234 240" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: bin/sketchtool 1.3 (252) - http://www.bohemiancoding.com/sketch -->
<title>bounce-inout.svg</title>
<desc>Created with bin/sketchtool.</desc>
<defs></defs>
<g id="combined" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="bounce-inout.svg" sketch:type="MSArtboardGroup">
<path d="M34,209.5 L34,22.1600037" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M34,22.5 C32.95,26.28 32.05,29.52 31,33.3 C33.1,33.3 34.9,33.3 37,33.3 C35.95,29.52 35.05,26.28 34,22.5 C34,22.5 34,22.5 34,22.5 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M24.5,194 L208.509995,194" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M208.5,194 C204.72,192.95 201.48,192.05 197.7,191 C197.7,193.1 197.7,194.9 197.7,197 C201.48,195.95 204.72,195.05 208.5,194 C208.5,194 208.5,194 208.5,194 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M35.3289777,193.635841 C35.3289777,193.635841 41.2333124,187.095281 52.2325098,193.635839 C55.4414764,183.659866 71.0514816,178.107189 80.7686063,193.635839 C89.032676,167.620814 117,110.452183 144.182478,194.552328 C148.063747,176.586161 175.037321,10.6423763 208.465749,22.4456533" id="Path-747" stroke="#EE6B47" stroke-width="3" stroke-linejoin="bevel" sketch:type="MSShapeGroup"></path>
<text id="0" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="212">0</tspan>
</text>
<text id="1" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="36">1</tspan>
</text>
<text id="-2" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="200" y="212">1</tspan>
</text>
<path d="M35.4840461,192.776816 C53.45735,186.177656 69.3490979,170.128038 97.137513,18.4980531 C102.051415,32.4334475 112.013077,63.0795933 127.058929,63.996791 C142.104781,64.9139886 156.560556,31.0473534 160.222221,20.3348259 C166.618848,28.1959597 165.111566,31.4251632 174.958382,31.425163 C184.805198,31.4251628 190.347191,21.8729943 191.581215,20.6199652 C193.7855,22.5969315 202.177314,24.4036062 206.959731,21.4508296" id="Path-770" stroke="#62C0DC" stroke-width="3" stroke-linejoin="bevel" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="234px" height="240px" viewBox="0 0 234 240" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: bin/sketchtool 1.3 (252) - http://www.bohemiancoding.com/sketch -->
<title>circ-ease.svg</title>
<desc>Created with bin/sketchtool.</desc>
<defs></defs>
<g id="combined" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="circ-ease.svg" sketch:type="MSArtboardGroup">
<path d="M34,209.5 L34,22.1600037" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M34,22.5 C32.95,26.28 32.05,29.52 31,33.3 C33.1,33.3 34.9,33.3 37,33.3 C35.95,29.52 35.05,26.28 34,22.5 C34,22.5 34,22.5 34,22.5 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M24.5,194 L208.509995,194" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M208.5,194 C204.72,192.95 201.48,192.05 197.7,191 C197.7,193.1 197.7,194.9 197.7,197 C201.48,195.95 204.72,195.05 208.5,194 C208.5,194 208.5,194 208.5,194 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M35.1598321,193.734972 C116.357678,193.734973 200.574538,141.537458 208.465749,22.4456533" id="Path-747" stroke="#EE6B47" stroke-width="3" stroke-linejoin="bevel" sketch:type="MSShapeGroup"></path>
<path d="M35.1598321,193.734972 C116.357678,193.734973 200.574538,141.537458 208.465749,22.4456533" id="Path-748" stroke="#8DB173" stroke-width="3" stroke-linejoin="bevel" sketch:type="MSShapeGroup" transform="translate(121.812790, 108.090312) scale(-1, -1) translate(-121.812790, -108.090312) "></path>
<text id="0" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="212">0</tspan>
</text>
<text id="1" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="36">1</tspan>
</text>
<text id="-2" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="200" y="212">1</tspan>
</text>
<path d="M35.4840461,192.776816 C53.45735,186.177656 112.052703,195.594079 121.221885,109.458253 C130.391067,23.3224269 202.177314,24.4036062 206.959731,21.4508296" id="Path-770" stroke="#62C0DC" stroke-width="3" stroke-linejoin="bevel" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="234px" height="240px" viewBox="0 0 234 240" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: bin/sketchtool 1.3 (252) - http://www.bohemiancoding.com/sketch -->
<title>circ.svg</title>
<desc>Created with bin/sketchtool.</desc>
<defs></defs>
<g id="combined" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="circ.svg" sketch:type="MSArtboardGroup">
<path d="M34,209.5 L34,22.1600037" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M34,22.5 C32.95,26.28 32.05,29.52 31,33.3 C33.1,33.3 34.9,33.3 37,33.3 C35.95,29.52 35.05,26.28 34,22.5 C34,22.5 34,22.5 34,22.5 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M24.5,194 L208.509995,194" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M208.5,194 C204.72,192.95 201.48,192.05 197.7,191 C197.7,193.1 197.7,194.9 197.7,197 C201.48,195.95 204.72,195.05 208.5,194 C208.5,194 208.5,194 208.5,194 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M35.3289777,193.635841 C35.3289777,193.635841 189.874769,197.008001 208.465749,22.4456533" id="Path-747" stroke="#EE6B47" stroke-width="3" sketch:type="MSShapeGroup"></path>
<text id="0" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="212">0</tspan>
</text>
<text id="1" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="36">1</tspan>
</text>
<text id="-2" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="200" y="212">1</tspan>
</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="233px" height="388px" viewBox="0 0 233 388" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: bin/sketchtool 1.3 (252) - http://www.bohemiancoding.com/sketch -->
<title>elastic.svg</title>
<desc>Created with bin/sketchtool.</desc>
<defs></defs>
<g id="combined" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="elastic.svg" sketch:type="MSArtboardGroup">
<path d="M34,365 L34,22.1600037" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M34,23 C32.95,26.78 32.05,30.02 31,33.8 C33.1,33.8 34.9,33.8 37,33.8 C35.95,30.02 35.05,26.78 34,23 C34,23 34,23 34,23 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M24.5,194 L208.509995,194" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M208.5,194 C204.72,192.95 201.48,192.05 197.7,191 C197.7,193.1 197.7,194.9 197.7,197 C201.48,195.95 204.72,195.05 208.5,194 C208.5,194 208.5,194 208.5,194 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M34.8792035,192.69782 C38.3217915,192.697818 46.5362784,191.195974 53.4936997,193.038137 C62.0206897,195.295885 61.5154635,189.622956 87.0139157,194.339254 C100.114357,196.762365 100.423927,183.608251 115.161483,194.900075 C135.318831,210.34451 133.877092,159.362737 148.519851,194.677907 C151.940119,202.926853 155.398942,217.279032 158.65332,214.286779 C161.563227,211.611251 163.848094,194.907207 173.23036,150.175435 C177.841468,128.191083 188.232669,296.296579 192.347319,280.535848 C201.966406,243.690946 203.555755,39.1411041 207.337233,22.0938619" id="Path-747" stroke="#EE6B47" stroke-width="3" sketch:type="MSShapeGroup"></path>
<text id="0" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="212">0</tspan>
</text>
<text id="1" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="36">1</tspan>
</text>
<text id="-2" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="200" y="212">1</tspan>
</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="234px" height="240px" viewBox="0 0 234 240" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: bin/sketchtool 1.3 (252) - http://www.bohemiancoding.com/sketch -->
<title>linear.svg</title>
<desc>Created with bin/sketchtool.</desc>
<defs></defs>
<g id="combined" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="linear.svg" sketch:type="MSArtboardGroup">
<path d="M34,209.5 L34,22.1600037" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M34,22.5 C32.95,26.28 32.05,29.52 31,33.3 C33.1,33.3 34.9,33.3 37,33.3 C35.95,29.52 35.05,26.28 34,22.5 C34,22.5 34,22.5 34,22.5 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M24.5,194 L208.509995,194" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M208.5,194 C204.72,192.95 201.48,192.05 197.7,191 C197.7,193.1 197.7,194.9 197.7,197 C201.48,195.95 204.72,195.05 208.5,194 C208.5,194 208.5,194 208.5,194 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M35.3289777,193.635841 L207.337233,22.0938619" id="Path-747" stroke="#EE6B47" stroke-width="3" sketch:type="MSShapeGroup"></path>
<text id="0" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="212">0</tspan>
</text>
<text id="1" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="36">1</tspan>
</text>
<text id="-2" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="200" y="212">1</tspan>
</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<link type="text/css" rel="stylesheet" href="animate.css">
<script src="move.js"></script>
</head>
<body>
<div onclick="move(this.children[0])" class="example_path">
<div class="example_block"></div>
</div>
</body>
</html>

View file

@ -0,0 +1,30 @@
<!DOCTYPE HTML>
<html>
<head>
<link type="text/css" rel="stylesheet" href="animate.css">
</head>
<body>
<script>
function move(elem) {
var left = 0; // начальное значение
function frame() { // функция для отрисовки
left++;
elem.style.left = left + 'px'
if (left == 100) {
clearInterval(timer); // завершить анимацию
}
}
var timer = setInterval(frame, 10) // рисовать каждые 10мс
}
</script>
<div onclick="move(this.children[0])" class="example_path">
<div class="example_block"></div>
</div>
</body>
</html>

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="234px" height="240px" viewBox="0 0 234 240" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: bin/sketchtool 1.3 (252) - http://www.bohemiancoding.com/sketch -->
<title>quad.svg</title>
<desc>Created with bin/sketchtool.</desc>
<defs></defs>
<g id="combined" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="quad.svg" sketch:type="MSArtboardGroup">
<path d="M34,209.5 L34,22.1600037" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M34,22.5 C32.95,26.28 32.05,29.52 31,33.3 C33.1,33.3 34.9,33.3 37,33.3 C35.95,29.52 35.05,26.28 34,22.5 C34,22.5 34,22.5 34,22.5 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M24.5,194 L208.509995,194" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M208.5,194 C204.72,192.95 201.48,192.05 197.7,191 C197.7,193.1 197.7,194.9 197.7,197 C201.48,195.95 204.72,195.05 208.5,194 C208.5,194 208.5,194 208.5,194 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M35.3289777,193.635841 C35.3289777,193.635841 113.802694,208.841146 207.337233,22.0938619" id="Path-747" stroke="#EE6B47" stroke-width="3" sketch:type="MSShapeGroup"></path>
<text id="0" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="212">0</tspan>
</text>
<text id="1" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="36">1</tspan>
</text>
<text id="-2" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="200" y="212">1</tspan>
</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="234px" height="240px" viewBox="0 0 234 240" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: bin/sketchtool 1.3 (252) - http://www.bohemiancoding.com/sketch -->
<title>quint.svg</title>
<desc>Created with bin/sketchtool.</desc>
<defs></defs>
<g id="combined" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="quint.svg" sketch:type="MSArtboardGroup">
<path d="M34,209.5 L34,22.1600037" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M34,22.5 C32.95,26.28 32.05,29.52 31,33.3 C33.1,33.3 34.9,33.3 37,33.3 C35.95,29.52 35.05,26.28 34,22.5 C34,22.5 34,22.5 34,22.5 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M24.5,194 L208.509995,194" id="Line" stroke="#E8C48E" stroke-width="2" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
<path id="Line-decoration-1" d="M208.5,194 C204.72,192.95 201.48,192.05 197.7,191 C197.7,193.1 197.7,194.9 197.7,197 C201.48,195.95 204.72,195.05 208.5,194 C208.5,194 208.5,194 208.5,194 Z" stroke="#E8C48E" stroke-width="2" stroke-linecap="square"></path>
<path d="M35.3289777,193.635841 C149.458906,196.88389 171.361738,184.274633 207.337233,22.0938619" id="Path-747" stroke="#EE6B47" stroke-width="3" sketch:type="MSShapeGroup"></path>
<text id="0" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="212">0</tspan>
</text>
<text id="1" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="17" y="36">1</tspan>
</text>
<text id="-2" sketch:type="MSTextLayer" font-family="Consolas" font-size="14" font-weight="bold" fill="#8A704D">
<tspan x="200" y="212">1</tspan>
</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<link type="text/css" rel="stylesheet" href="animate.css">
<script src="width.js"></script>
</head>
<body>
<div onclick="stretch(this.children[0])" class="example_path">
<div class="example_block"></div>
</div>
</body>
</html>