diff --git a/10-regular-expressions/03-regexp-character-classes/article.md b/10-regular-expressions/03-regexp-character-classes/article.md index fd633927..baee2dd9 100644 --- a/10-regular-expressions/03-regexp-character-classes/article.md +++ b/10-regular-expressions/03-regexp-character-classes/article.md @@ -93,7 +93,7 @@ When the pattern contains `pattern:\b`, it tests that the position in string fit - String end, and the last string character is `\w`. - Inside the string: from one side is `\w`, from the other side -- not `\w`. -For instance, in the string `subject:Hello, Java!` the following positions fit `\b`: +For instance, in the string `subject:Hello, Java!` the following positions match `\b`: ![](hello-java-boundaries.png) diff --git a/5-animation/1-bezier-curve/article.md b/5-animation/1-bezier-curve/article.md new file mode 100644 index 00000000..dc37e9b8 --- /dev/null +++ b/5-animation/1-bezier-curve/article.md @@ -0,0 +1,183 @@ +# Bezier curve + +Bezier curves are used in computer graphics to draw shapes, for CSS animation and in many other places. + +They are actually a very simple thing, worth to study once and then feel comfortable in the world of vector graphics and advanced animations. + +[cut] + +## Control points + +A [bezier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve) is defined by control points. + +There may be 2, 3, 4 or more. + +For instance, two points curve: + +![](bezier2.png) + +Three points curve: + +![](bezier3.png) + +Four points curve: + +![](bezier4.png) + +If you look closely at these curves, you can immediately notice: + +1. **Points are not always on curve.** That's perfectly normal, later we'll see how the curve is built. +2. **Curve order equals the number of points minus one**. +For two points we have a linear curve (that's a straight line), for three points -- quadratic curve (parabolic), for three points -- cubic curve. +3. **A curve is always inside the [convex hull](https://en.wikipedia.org/wiki/Convex_hull) of control points:** + + ![](bezier4-e.png) ![](bezier3-e.png) + + Because of that last property, in computer graphics it's possible to optimize intersection tests. If convex hulls do not intersect, then curves do not either. + +The main value of Bezier curves for drawing -- by moving the points the curve is changing *in intuitively obvious way*. + +Try to move points using a mouse in the example below: + +[iframe src="demo.svg?nocpath=1&p=0,0,0.5,0,0.5,1,1,1" height=370] + +**As you can notice, the curve stretches along the tangential lines 1 -> 2 и 3 -> 4.** + +After some practice it becomes obvious how to place points to get the needed curve. And by connecting several curves we can get practically anything. + +Here are some examples: + +![](bezier-car.png) ![](bezier-letter.png) ![](bezier-vase.png) + +## Maths + +A Bezier curve can be described using a mathematical formula. + +As we'll see soon -- there's no need to know it. But for completeness -- here you go. + +We have coordinates of control points Pi: the first control point has coordinates P1 = (x1, y1), the second: P2 = (x2, y2), and so on. + +Then the curve coordinates are described by the equation that depends on the parameter `t` from the segment `[0,1]`. + +- For two points: + + P = (1-t)P1 + tP2 +- For three points: + + P = (1−t)2P1 + 2(1−t)tP2 + t2P3 +- For four points: + + P = (1−t)3P1 + 3(1−t)2tP2 +3(1−t)t2P3 + t3P4 + +These are vector equations. + +We can rewrite them coordinate-by-coordinate, for instance the 3-point variant: + +- x = (1−t)2x1 + 2(1−t)tx2 + t2x3 +- y = (1−t)2y1 + 2(1−t)ty2 + t2y3 + +Instead of x1, y1, x2, y2, x3, y3 we should put coordinates of 3 control points, and `t` runs from `0` to `1`. The set of values `(x,y)` for each `t` forms the curve. + +That's probably too scientific, not very obvious why curves look like that, and how they depend on control points. + +Another drawing algorithm may be easier to understand. + +## De Casteljau's algorithm + +[De Casteljau's algorithm](https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm) is identical to the mathematical definition of the curve, but visually shows how it is built. + +Let's explain it on the 3-points example. + +Here's the demo. Points can be moved by the mouse. Press the "play" button to run it. + +[iframe src="demo.svg?p=0,0,0.5,1,1,0&animate=1" height=370] + +**De Casteljau's algorithm of building the 3-point bezier curve:** + +1. Draw control points. In the demo above they are labeled: `1`, `2`, `3`. +2. Build segments between control points 1 -> 2 -> 3. In the demo above they are brown. +3. The parameter `t` moves from `0` to `1`. In the example above the step `0.05` is used: the loop goes over `0, 0.05, 0.1, 0.15, ... 0.95, 1`. + + For each of these values of `t`: + + - On each brown segment we take a point located on the distance proportional to `t` from its beginning. As there are two segments, we have two points. + + For instance, for `t=0` -- both points will be at the beginning of segments, and for `t=0.25` -- on the 25% of segment length from the beginning, for `t=0.5` -- 50%(the middle), for `t=1` -- in the end of segments. + + - Connect the points. On the picture below the connecting segment is painted blue. + + +| For `t=0.25` | For `t=0.5` | +| ------------------------ | ---------------------- | +| ![](bezier3-draw1.png) | ![](bezier3-draw2.png) | + +4. On the new segment we take a point on the distance proportional to `t`. That is, for `t=0.25` (the left picture) we have a point at the end of the left quarter of the segment, and for `t=0.5` (the right picture) -- in the middle of the segment. On pictures above that point is red. + +5. As `t` runs from `0` to `1`, every value of `t` adds a point to the curve. The set of such points forms the Bezier curve. It's red and parabolic on the pictures above. + +That was a process for 3 points. But the same is for 4 points. + +The demo for 4 points (points can be moved by mouse): + +[iframe src="demo.svg?p=0,0,0.5,0,0.5,1,1,1&animate=1" height=370] + +The algorithm: + +- Control points are connected by segments: 1 -> 2, 2 -> 3, 3 -> 4. We have 3 brown segments. +- For each `t` in the interval from `0` to `1`: + - We take points on these segments on the distance proportional to `t` from the beginning. These points are connected, so that we have two green segments. + - On these segments we take points proportional to `t`. We get one blue segment. + - On the blue segment we take a point proportional to `t`. On the example above it's red. +- These points together form the curve. + +The algorithm is recursive. For each `t` from `0` to `1` we have first N segments, then take points of them and connect -- N-1 segments and so on till we have one point. These make the curve. + +Press the "play" button in the example above to see it in action. + +Move examples of curves: + +[iframe src="demo.svg?p=0,0,0,0.75,0.25,1,1,1&animate=1" height=370] + +With other points: + +[iframe src="demo.svg?p=0,0,1,0.5,0,0.5,1,1&animate=1" height=370] + +Loop form: + +[iframe src="demo.svg?p=0,0,1,0.5,0,1,0.5,0&animate=1" height=370] + +Not smooth Bezier curve: + +[iframe src="demo.svg?p=0,0,1,1,0,1,1,0&animate=1" height=370] + +As the algorithm is recursive, we can build Bezier curves of any order: using 5, 6 or more control points. But on practice they are less useful. Usually we take 2-3 points, and for complex lines glue several curves together. That's simpler for support and in calculations. + +```smart header="How to draw a curve *through* given points?" +We use control points for a Bezier curve. As we can see, they are not on the curve. Or, to be precise, the first and the last one do belong to curve, but others don't. + +Sometimes we have another task: to draw a curve *through several points*, so that all of them are on a single smooth curve. That task is called [interpolation](https://en.wikipedia.org/wiki/Interpolation), and here we don't cover it. + +There are mathematical formulas for such curves, for instance [Lagrange polynomial](https://en.wikipedia.org/wiki/Lagrange_polynomial). + +In computer graphics [spline interpolation](https://en.wikipedia.org/wiki/Spline_interpolation) is often used to build smooth curves that connect many points. +``` + +## Summary + +Bezier curves are defined by their control points. + +We saw two definitions of Bezier curves: + +1. Using a mathematical formulas. +2. Using a drawing process: De Casteljau's algorithm + +Good properties of Bezier curves: + +- We can draw smooth lines with a mouse by moving around control points. +- Complex shapes can be made of several Bezier curves. + +Usage: + +- In computer graphics, modeling, vector graphic editors. Fonts are described by Bezier curves. +- In web development -- for graphics on Canvas and in the SVG format. By the way, "live" examples above are written in SVG. They are actually a single SVG document that is given different points as parameters. You can open it in a separate window and see the source: [demo.svg](demo.svg?p=0,0,1,0.5,0,0.5,1,1&animate=1). +- In CSS animation to describe the path and speed of animation. diff --git a/5-animation/1-bezier-curve/bezier-car.png b/5-animation/1-bezier-curve/bezier-car.png new file mode 100644 index 00000000..5df005c3 Binary files /dev/null and b/5-animation/1-bezier-curve/bezier-car.png differ diff --git a/5-animation/1-bezier-curve/bezier-car@2x.png b/5-animation/1-bezier-curve/bezier-car@2x.png new file mode 100644 index 00000000..990ecac3 Binary files /dev/null and b/5-animation/1-bezier-curve/bezier-car@2x.png differ diff --git a/5-animation/1-bezier-curve/bezier-letter.png b/5-animation/1-bezier-curve/bezier-letter.png new file mode 100644 index 00000000..636c2abe Binary files /dev/null and b/5-animation/1-bezier-curve/bezier-letter.png differ diff --git a/5-animation/1-bezier-curve/bezier-letter@2x.png b/5-animation/1-bezier-curve/bezier-letter@2x.png new file mode 100644 index 00000000..86e8f80e Binary files /dev/null and b/5-animation/1-bezier-curve/bezier-letter@2x.png differ diff --git a/5-animation/1-bezier-curve/bezier-vase.png b/5-animation/1-bezier-curve/bezier-vase.png new file mode 100644 index 00000000..1fdc08f7 Binary files /dev/null and b/5-animation/1-bezier-curve/bezier-vase.png differ diff --git a/5-animation/1-bezier-curve/bezier-vase@2x.png b/5-animation/1-bezier-curve/bezier-vase@2x.png new file mode 100644 index 00000000..e60ced0d Binary files /dev/null and b/5-animation/1-bezier-curve/bezier-vase@2x.png differ diff --git a/5-animation/1-bezier-curve/bezier2.png b/5-animation/1-bezier-curve/bezier2.png new file mode 100644 index 00000000..cbad0a36 Binary files /dev/null and b/5-animation/1-bezier-curve/bezier2.png differ diff --git a/5-animation/1-bezier-curve/bezier2@2x.png b/5-animation/1-bezier-curve/bezier2@2x.png new file mode 100644 index 00000000..6dbf1bfd Binary files /dev/null and b/5-animation/1-bezier-curve/bezier2@2x.png differ diff --git a/5-animation/1-bezier-curve/bezier3-draw1.png b/5-animation/1-bezier-curve/bezier3-draw1.png new file mode 100644 index 00000000..177af247 Binary files /dev/null and b/5-animation/1-bezier-curve/bezier3-draw1.png differ diff --git a/5-animation/1-bezier-curve/bezier3-draw1@2x.png b/5-animation/1-bezier-curve/bezier3-draw1@2x.png new file mode 100644 index 00000000..badd242d Binary files /dev/null and b/5-animation/1-bezier-curve/bezier3-draw1@2x.png differ diff --git a/5-animation/1-bezier-curve/bezier3-draw2.png b/5-animation/1-bezier-curve/bezier3-draw2.png new file mode 100644 index 00000000..f27ebcd7 Binary files /dev/null and b/5-animation/1-bezier-curve/bezier3-draw2.png differ diff --git a/5-animation/1-bezier-curve/bezier3-draw2@2x.png b/5-animation/1-bezier-curve/bezier3-draw2@2x.png new file mode 100644 index 00000000..129eb36e Binary files /dev/null and b/5-animation/1-bezier-curve/bezier3-draw2@2x.png differ diff --git a/5-animation/1-bezier-curve/bezier3-e.png b/5-animation/1-bezier-curve/bezier3-e.png new file mode 100644 index 00000000..f5b9e628 Binary files /dev/null and b/5-animation/1-bezier-curve/bezier3-e.png differ diff --git a/5-animation/1-bezier-curve/bezier3-e@2x.png b/5-animation/1-bezier-curve/bezier3-e@2x.png new file mode 100644 index 00000000..bc4da5f7 Binary files /dev/null and b/5-animation/1-bezier-curve/bezier3-e@2x.png differ diff --git a/5-animation/1-bezier-curve/bezier3.png b/5-animation/1-bezier-curve/bezier3.png new file mode 100644 index 00000000..53d42f1d Binary files /dev/null and b/5-animation/1-bezier-curve/bezier3.png differ diff --git a/5-animation/1-bezier-curve/bezier3@2x.png b/5-animation/1-bezier-curve/bezier3@2x.png new file mode 100644 index 00000000..80fef732 Binary files /dev/null and b/5-animation/1-bezier-curve/bezier3@2x.png differ diff --git a/5-animation/1-bezier-curve/bezier4-e.png b/5-animation/1-bezier-curve/bezier4-e.png new file mode 100644 index 00000000..1761ce21 Binary files /dev/null and b/5-animation/1-bezier-curve/bezier4-e.png differ diff --git a/5-animation/1-bezier-curve/bezier4-e@2x.png b/5-animation/1-bezier-curve/bezier4-e@2x.png new file mode 100644 index 00000000..b21b8869 Binary files /dev/null and b/5-animation/1-bezier-curve/bezier4-e@2x.png differ diff --git a/5-animation/1-bezier-curve/bezier4.png b/5-animation/1-bezier-curve/bezier4.png new file mode 100644 index 00000000..9176f973 Binary files /dev/null and b/5-animation/1-bezier-curve/bezier4.png differ diff --git a/5-animation/1-bezier-curve/bezier4@2x.png b/5-animation/1-bezier-curve/bezier4@2x.png new file mode 100644 index 00000000..f4e8d790 Binary files /dev/null and b/5-animation/1-bezier-curve/bezier4@2x.png differ diff --git a/5-animation/1-bezier/demo.svg b/5-animation/1-bezier-curve/demo.svg similarity index 100% rename from 5-animation/1-bezier/demo.svg rename to 5-animation/1-bezier-curve/demo.svg diff --git a/5-animation/1-bezier/pause.png b/5-animation/1-bezier-curve/pause.png similarity index 100% rename from 5-animation/1-bezier/pause.png rename to 5-animation/1-bezier-curve/pause.png diff --git a/5-animation/1-bezier/play.png b/5-animation/1-bezier-curve/play.png similarity index 100% rename from 5-animation/1-bezier/play.png rename to 5-animation/1-bezier-curve/play.png diff --git a/5-animation/1-bezier/article.md b/5-animation/1-bezier/article.md deleted file mode 100644 index df75014a..00000000 --- a/5-animation/1-bezier/article.md +++ /dev/null @@ -1,181 +0,0 @@ -# Bezier curves - -Bezier curves are used in computer graphics ... - - -Кривые Безье используются в компьютерной графике для рисования плавных изгибов, в CSS-анимации и много где ещё. - -Несмотря на "умное" название -- это очень простая штука. - -В принципе, можно создавать анимацию и без знания кривых Безье, но стоит один раз изучить эту тему хотя бы для того, чтобы в дальнейшем с комфортом пользоваться этим замечательным инструментом. Тем более что в мире векторной графики и продвинутых анимаций без них никак. - -[cut] - -## Виды кривых Безье - -[Кривая Безье](http://ru.wikipedia.org/wiki/%D0%9A%D1%80%D0%B8%D0%B2%D0%B0%D1%8F_%D0%91%D0%B5%D0%B7%D1%8C%D0%B5) задаётся опорными точками. - -Их может быть две, три, четыре или больше. Например: - -По двум точкам: - -![](bezier2.png) - -По трём точкам: - -![](bezier3.png) - -По четырём точкам: - -![](bezier4.png) - -Если вы посмотрите внимательно на эти кривые, то "на глазок" заметите: - -1. **Точки не всегда на кривой.** Это совершенно нормально, как именно строится кривая мы рассмотрим чуть позже. -2. **Степень кривой равна числу точек минус один**. -Для двух точек -- это линейная кривая (т.е. прямая), для трёх точек -- квадратическая кривая (парабола), для четырёх -- кубическая. -3. **Кривая всегда находится внутри [выпуклой оболочки](http://ru.wikipedia.org/wiki/%D0%92%D1%8B%D0%BF%D1%83%D0%BA%D0%BB%D0%B0%D1%8F_%D0%BE%D0%B1%D0%BE%D0%BB%D0%BE%D1%87%D0%BA%D0%B0), образованной опорными точками:** - - ![](bezier4-e.png) ![](bezier3-e.png) - - Благодаря последнему свойству в компьютерной графике можно оптимизировать проверку пересечений двух кривых. Если их выпуклые оболочки не пересекаются, то и кривые тоже не пересекутся. - -Основная ценность кривых Безье для рисования -- в том, что, двигая точки, кривую можно менять, причём кривая при этом *меняется интуитивно понятным образом*. - -Попробуйте двигать точки мышью в примере ниже: - -[iframe src="demo.svg?nocpath=1&p=0,0,0.5,0,0.5,1,1,1" height=370] - -**Как можно заметить, кривая натянута по касательным 1 -> 2 и 3 -> 4.** - -После небольшой практики становится понятно, как расположить точки, чтобы получить нужную форму. А, соединяя несколько кривых, можно получить практически что угодно. - -Вот некоторые примеры: - -![](bezier-car.png) ![](bezier-letter.png) ![](bezier-vase.png) - -## Математика - -У кривых Безье есть математическая формула. - -Как мы увидим далее, для пользования кривыми Безье знать её нет особенной необходимости, но для полноты картины -- вот она. - -**Координаты кривой описываются в зависимости от параметра `t⋲[0,1]`** - -- Для двух точек: - - P = (1-t)P1 + tP2 -- Для трёх точек: - - P = (1−t)2P1 + 2(1−t)tP2 + t2P3 -- Для четырёх точек: - - P = (1−t)3P1 + 3(1−t)2tP2 +3(1−t)t2P3 + t3P4 - -Вместо Pi нужно подставить координаты i-й опорной точки (xi, yi). - -Эти уравнения векторные, то есть для каждой из координат: - -- x = (1−t)2x1 + 2(1−t)tx2 + t2x3 -- y = (1−t)2y1 + 2(1−t)ty2 + t2y3 - -Вместо x1, y1, x2, y2, x3, y3 подставляются координаты трёх опорных точек, и в то время как `t` пробегает множество от `0` до `1`, соответствующие значения `(x, y)` как раз и образуют кривую. - -Впрочем, это чересчур наукообразно, не очень понятно, почему кривые именно такие, и как зависят от опорных точек. С этим нам поможет разобраться другой, более наглядный алгоритм. - -## Рисование "де Кастельжо" - -[Метод де Кастельжо](http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%B5_%D0%9A%D0%B0%D1%81%D1%82%D0%B5%D0%BB%D1%8C%D0%B6%D0%BE) идентичен математическому определению кривой и наглядно показывает, как она строится. - -Посмотрим его на примере трёх точек (точки можно двигать). Нажатие на кнопку "play" запустит демонстрацию. - -[iframe src="demo.svg?p=0,0,0.5,1,1,0&animate=1" height=370] - -**Алгоритм построения кривой по "методу де Кастельжо":** - -1. Рисуем опорные точки. В примере выше это `1`, `2`, `3`. -2. Строятся отрезки между опорными точками 1 -> 2 -> 3. На рисунке выше они коричневые. -3. Параметр `t` пробегает значения от `0` до `1`. В примере выше использован шаг `0.05`, т.е. в цикле `0, 0.05, 0.1, 0.15, ... 0.95, 1`. - - Для каждого из этих значений `t`: - - - На каждом из коричневых отрезков берётся точка, находящаяся от начала на расстоянии от 0 до `t` пропорционально длине. Так как коричневых отрезков -- два, то и точек две штуки. - - Например, при `t=0` -- точки будут в начале, при `t=0.25` -- на расстоянии в 25% от начала отрезка, при `t=0.5` -- 50%(на середине), при `t=1` -- в конце отрезков. - - - Эти точки соединяются. На рисунке ниже соединяющий их отрезок изображён синим. - - -| При `t=0.25` | При `t=0.5` | -| ------------------------ | ---------------------- | -| ![](bezier3-draw1.png) | ![](bezier3-draw2.png) | - -4. На получившемся отрезке берётся точка на расстоянии, соответствующем `t`. То есть, для `t=0.25` (первый рисунок) получаем точку в конце первой четверти отрезка, для `t=0.5` (второй рисунок) -- в середине отрезка. На рисунках выше эта точка отмечена красным. - -5. По мере того как `t` пробегает последовательность от `0` до `1`, каждое значение `t` добавляет к красной кривой точку. **Совокупность таких точек для всех значений `t` образуют кривую Безье.** - -Это был процесс для построения по трём точкам. Но то же самое происходит и с четырьмя точками. - -Демо для четырёх точек (точки можно двигать): - -[iframe src="demo.svg?p=0,0,0.5,0,0.5,1,1,1&animate=1" height=370] - -Алгоритм: - -- Точки по порядку соединяются отрезками: 1 -> 2, 2 -> 3, 3 -> 4. Получается три коричневых отрезка. -- На отрезках берутся точки, соответствующие текущему `t`, соединяются. Получается два зелёных отрезка. -- На этих отрезках берутся точки, соответствующие текущему `t`, соединяются. Получается один синий отрезок. -- На синем отрезке берётся точка, соответствующая текущему `t`. При запуске примера выше она красная. -- Эти точки описывают кривую. - -Этот алгоритм рекурсивен. Для каждого `t` из интервала от `0` до `1` по этому правилу, соединяя точки на соответствующем расстоянии, из 4 отрезков делается 3, затем из 3 так же делается 2, затем из 2 отрезков -- точка, описывающая кривую для данного значения `t`. - -Нажмите на кнопку "play" в примере выше, чтобы увидеть это в действии. - -Ещё примеры кривых: - -[iframe src="demo.svg?p=0,0,0,0.75,0.25,1,1,1&animate=1" height=370] - -С другими точками: - -[iframe src="demo.svg?p=0,0,1,0.5,0,0.5,1,1&animate=1" height=370] - -Петелька: - -[iframe src="demo.svg?p=0,0,1,0.5,0,1,0.5,0&animate=1" height=370] - -Пример негладкой кривой Безье: - -[iframe src="demo.svg?p=0,0,1,1,0,1,1,0&animate=1" height=370] - -Так как алгоритм рекурсивен, то аналогичным образом могут быть построены кривые Безье и более высокого порядка: по пяти точкам, шести и так далее. Однако на практике они менее полезны. Обычно используются 2-3 точки, а для сложных линий несколько кривых соединяются. Это гораздо проще с точки зрения поддержки и расчётов. - -```smart header="Как провести кривую Безье *через* нужные точки?" -В задаче построения кривой Безье используются "опорные точки". Они, как можно видеть из примеров выше, не лежат на кривой. Точнее говоря, только первая и последняя лежат на кривой, а промежуточные -- нет. - -Иногда возникает другая задача: провести кривую именно *через нужные точки*, чтобы все они лежали на некой плавной кривой, удовлетворяющей определённым требованиям. Такая задача называется [интерполяцией](http://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D1%80%D0%BF%D0%BE%D0%BB%D1%8F%D1%86%D0%B8%D1%8F), и здесь мы её не рассматриваем. - -Существуют математические формулы для таких построений, например [многочлен Лагранжа](http://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D1%80%D0%BF%D0%BE%D0%BB%D1%8F%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE%D1%87%D0%BB%D0%B5%D0%BD_%D0%9B%D0%B0%D0%B3%D1%80%D0%B0%D0%BD%D0%B6%D0%B0). - -Как правило, в компьютерной графике для построения плавных кривых, проходящих через несколько точек, используют кубические кривые, плавно переходящие одна в другую. Это называется [интерполяция сплайнами](http://ru.wikipedia.org/wiki/%D0%9A%D1%83%D0%B1%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D1%81%D0%BF%D0%BB%D0%B0%D0%B9%D0%BD). -``` - -## Итого - -Кривые Безье задаются опорными точками. - -Мы рассмотрели два определения кривых: - -1. Через математическую формулу. -2. Через процесс построения де Кастельжо. - -Их удобство в том, что: - -- Можно легко нарисовать плавные линии вручную, передвигая точки мышкой. -- Более сложные изгибы и линии можно составить, если соединить несколько кривых Безье. - -Применение: - -- В компьютерной графике, моделировании, в графических редакторах. Шрифты описываются с помощью кривых Безье. -- В веб-разработке -- для графики на Canvas или в формате SVG. Кстати, все живые примеры выше написаны на SVG. Фактически, это один SVG-документ, к которому точки передаются параметрами. Вы можете открыть его в отдельном окне и посмотреть исходник: [demo.svg](demo.svg?p=0,0,1,0.5,0,0.5,1,1&animate=1). -- В CSS-анимации, для задания траектории или скорости передвижения. diff --git a/5-animation/1-bezier/bezier-car.png b/5-animation/1-bezier/bezier-car.png deleted file mode 100644 index 5b04af23..00000000 Binary files a/5-animation/1-bezier/bezier-car.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier-car@2x.png b/5-animation/1-bezier/bezier-car@2x.png deleted file mode 100644 index 47f80ed9..00000000 Binary files a/5-animation/1-bezier/bezier-car@2x.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier-letter.png b/5-animation/1-bezier/bezier-letter.png deleted file mode 100644 index d32e4733..00000000 Binary files a/5-animation/1-bezier/bezier-letter.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier-letter@2x.png b/5-animation/1-bezier/bezier-letter@2x.png deleted file mode 100644 index 168306d6..00000000 Binary files a/5-animation/1-bezier/bezier-letter@2x.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier-vase.png b/5-animation/1-bezier/bezier-vase.png deleted file mode 100644 index e469eb49..00000000 Binary files a/5-animation/1-bezier/bezier-vase.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier-vase@2x.png b/5-animation/1-bezier/bezier-vase@2x.png deleted file mode 100644 index ec213884..00000000 Binary files a/5-animation/1-bezier/bezier-vase@2x.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier2.png b/5-animation/1-bezier/bezier2.png deleted file mode 100644 index 574b2054..00000000 Binary files a/5-animation/1-bezier/bezier2.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier2@2x.png b/5-animation/1-bezier/bezier2@2x.png deleted file mode 100644 index 8d699b8b..00000000 Binary files a/5-animation/1-bezier/bezier2@2x.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier3-draw1.png b/5-animation/1-bezier/bezier3-draw1.png deleted file mode 100644 index 3cf79c9b..00000000 Binary files a/5-animation/1-bezier/bezier3-draw1.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier3-draw1@2x.png b/5-animation/1-bezier/bezier3-draw1@2x.png deleted file mode 100644 index 25d70a14..00000000 Binary files a/5-animation/1-bezier/bezier3-draw1@2x.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier3-draw2.png b/5-animation/1-bezier/bezier3-draw2.png deleted file mode 100644 index 39f9c2f8..00000000 Binary files a/5-animation/1-bezier/bezier3-draw2.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier3-draw2@2x.png b/5-animation/1-bezier/bezier3-draw2@2x.png deleted file mode 100644 index 77b6dafc..00000000 Binary files a/5-animation/1-bezier/bezier3-draw2@2x.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier3-e.png b/5-animation/1-bezier/bezier3-e.png deleted file mode 100644 index a71ed0a3..00000000 Binary files a/5-animation/1-bezier/bezier3-e.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier3-e@2x.png b/5-animation/1-bezier/bezier3-e@2x.png deleted file mode 100644 index d9e66915..00000000 Binary files a/5-animation/1-bezier/bezier3-e@2x.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier3.png b/5-animation/1-bezier/bezier3.png deleted file mode 100644 index 0ac10ae7..00000000 Binary files a/5-animation/1-bezier/bezier3.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier3@2x.png b/5-animation/1-bezier/bezier3@2x.png deleted file mode 100644 index d04eb1e6..00000000 Binary files a/5-animation/1-bezier/bezier3@2x.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier4-e.png b/5-animation/1-bezier/bezier4-e.png deleted file mode 100644 index 0d9332be..00000000 Binary files a/5-animation/1-bezier/bezier4-e.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier4-e@2x.png b/5-animation/1-bezier/bezier4-e@2x.png deleted file mode 100644 index 937fa888..00000000 Binary files a/5-animation/1-bezier/bezier4-e@2x.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier4.png b/5-animation/1-bezier/bezier4.png deleted file mode 100644 index 5179d834..00000000 Binary files a/5-animation/1-bezier/bezier4.png and /dev/null differ diff --git a/5-animation/1-bezier/bezier4@2x.png b/5-animation/1-bezier/bezier4@2x.png deleted file mode 100644 index 9c00128c..00000000 Binary files a/5-animation/1-bezier/bezier4@2x.png and /dev/null differ diff --git a/5-animation/2-css-transitions/1-animate-logo-css/solution.md b/5-animation/2-css-animations/1-animate-logo-css/solution.md similarity index 100% rename from 5-animation/2-css-transitions/1-animate-logo-css/solution.md rename to 5-animation/2-css-animations/1-animate-logo-css/solution.md diff --git a/5-animation/2-css-transitions/1-animate-logo-css/solution.view/index.html b/5-animation/2-css-animations/1-animate-logo-css/solution.view/index.html similarity index 100% rename from 5-animation/2-css-transitions/1-animate-logo-css/solution.view/index.html rename to 5-animation/2-css-animations/1-animate-logo-css/solution.view/index.html diff --git a/5-animation/2-css-transitions/1-animate-logo-css/source.view/index.html b/5-animation/2-css-animations/1-animate-logo-css/source.view/index.html similarity index 100% rename from 5-animation/2-css-transitions/1-animate-logo-css/source.view/index.html rename to 5-animation/2-css-animations/1-animate-logo-css/source.view/index.html diff --git a/5-animation/2-css-transitions/1-animate-logo-css/task.md b/5-animation/2-css-animations/1-animate-logo-css/task.md similarity index 100% rename from 5-animation/2-css-transitions/1-animate-logo-css/task.md rename to 5-animation/2-css-animations/1-animate-logo-css/task.md diff --git a/5-animation/2-css-animations/2-animate-logo-bezier-css/bezier-up.png b/5-animation/2-css-animations/2-animate-logo-bezier-css/bezier-up.png new file mode 100644 index 00000000..91e2bfe5 Binary files /dev/null and b/5-animation/2-css-animations/2-animate-logo-bezier-css/bezier-up.png differ diff --git a/5-animation/2-css-animations/2-animate-logo-bezier-css/bezier-up@2x.png b/5-animation/2-css-animations/2-animate-logo-bezier-css/bezier-up@2x.png new file mode 100644 index 00000000..31384e53 Binary files /dev/null and b/5-animation/2-css-animations/2-animate-logo-bezier-css/bezier-up@2x.png differ diff --git a/5-animation/2-css-transitions/2-animate-logo-bezier-css/solution.md b/5-animation/2-css-animations/2-animate-logo-bezier-css/solution.md similarity index 100% rename from 5-animation/2-css-transitions/2-animate-logo-bezier-css/solution.md rename to 5-animation/2-css-animations/2-animate-logo-bezier-css/solution.md diff --git a/5-animation/2-css-transitions/2-animate-logo-bezier-css/solution.view/index.html b/5-animation/2-css-animations/2-animate-logo-bezier-css/solution.view/index.html similarity index 100% rename from 5-animation/2-css-transitions/2-animate-logo-bezier-css/solution.view/index.html rename to 5-animation/2-css-animations/2-animate-logo-bezier-css/solution.view/index.html diff --git a/5-animation/2-css-transitions/2-animate-logo-bezier-css/task.md b/5-animation/2-css-animations/2-animate-logo-bezier-css/task.md similarity index 100% rename from 5-animation/2-css-transitions/2-animate-logo-bezier-css/task.md rename to 5-animation/2-css-animations/2-animate-logo-bezier-css/task.md diff --git a/5-animation/2-css-animations/article.md b/5-animation/2-css-animations/article.md new file mode 100644 index 00000000..5c2b9925 --- /dev/null +++ b/5-animation/2-css-animations/article.md @@ -0,0 +1,422 @@ +# CSS-animations + +CSS animations allow to do simple animations without JavaScript at all. + +JavaScript can be used to control CSS animation and make them even better with a little of code. + +[cut] + +## CSS transitions [#css-transition] + +The idea of CSS transitions is simple. We describe a property and how its changes should be animated. When the property changes, the browser paints the animation. + +That is: all we need is to change the property. And the fluent transition is made by the browser. + +For instance, the CSS below animates changes of `background-color` for 3 seconds: + +```css +.animated { + transition-property: background-color; + transition-duration: 3s; +} +``` + +Now if an element has `.animated` class, any change of `background-color` is animated during 3 seconds. + +Click the button below to animate the background: + +```html run autorun height=60 + + + + + +``` + +There are 5 properties to describe CSS transitions: + +- `transition-property` +- `transition-duration` +- `transition-timing-function` +- `transition-delay` + +We'll cover them in a moment, for now let's note that the common `transition` property allows to declare them together in the order: `property duration timing-function delay`, and also animate multiple properties at once. + +For instance, this button animates both `color` and `font-size`: + +```html run height=80 autorun no-beautify + + + + + +``` + +Now let's cover animation properties one by one. + +## transition-property + +In `transition-property` we write a list of property to animate, for instance: `left`, `margin-left`, `height`, `color`. + +Not all properties can be animated, but [many of them](http://www.w3.org/TR/css3-transitions/#animatable-properties-). The value `all` means "animate all properties". + +## transition-duration + +In `transition-duration` we can specify how long the animation should take. The time should be in [CSS time format](http://www.w3.org/TR/css3-values/#time): in seconds `s` or milliseconds `ms`. + +## transition-delay + +In `transition-delay` we can specify the delay *before* the animation. For instance, if `transition-delay: 1s`, then animation starts after 1 second after the change. + +Negative values are also possible. Then the animation starts from the middle. For instance, if `transition-duration` is `2s`, and the delay is `-1s`, then the animation takes 1 second and starts from the half. + +Here's the animation shifts numbers from `0` to `9` using CSS `translate` property: + +[codetabs src="digits"] + +The `transform` property is animated like this: + +```css +#stripe.animate { + transform: translate(-90%); + transition-property: transform; + transition-duration: 9s; +} +``` + +In the example above JavaScript adds the class `.animate` to the element -- and the animation starts: + +```js +stripe.classList.add('animate'); +``` + +We can also start it "from the middle", from the exact number, e.g. corresponding to the current second, using the negative `transition-delay`. + +Here if you click the digit -- it starts the animation from the current second: + +[codetabs src="digits-negative-delay"] + +JavaScript does it by an extra line: + +```js +stripe.onclick = function() { + let sec = new Date().getSeconds() % 10; +*!* + // for instance, -3s here starts the animation from the 3rd second + stripe.style.transitionDelay = '-' + sec + 's'; +*/!* + stripe.classList.add('animate'); +}; +``` + +## transition-timing-function + +Timing function describes how the animation process is distributed along the time. Will it start slowly and then go fast or vise versa. + +That's the most complicated property from the first sight. But it becomes very simple if we devote a bit time to it. + +That property accepts two kinds of values: a Bezier curve or steps. Let's start from the curve, as it's used more often. + +### Bezier curve + +The timing function can be set as a [Bezier curve](/bezier-curve) with 4 control points that satisfies the conditions: + +1. First control point: `(0,0)`. +2. Last control point: `(1,1)`. +3. For intermediate points values of `x` must be in the interval `0..1`, `y` can be anything. + +The syntax for a Bezier curve in CSS: `cubic-bezier(x2, y2, x3, y3)`. Here we need to specify only 2nd and 3rd control points, because the 1st one is fixed to `(0,0)` and the 4th one is `(1,1)`. + +The timing function describes how fast the animation process goes in time. + +- The `x` axis is the time: `0` -- the starting moment, `1` -- the last moment of `transition-duration`. +- The `y` axis specifies the completion of the process: `0` -- the starting value of the property, `1` -- the final value. + +The simplest variant is when the animation goes uniformly, with the same linear speed. That can be specified by the curve `cubic-bezier(0, 0, 1, 1)`. + +Here's how that curve looks: + +![](bezier-linear.png) + +...As we can see, it's just a straight line. As the time (`x`) passes, the completion (`y`) of the animation steadily goes from `0` to `1`. + +The train in the example below goes from left to right with the permanent speed (click it): + +[codetabs src="train-linear"] + +The CSS `transition` is bazed on that curve: + +```css +.train { + left: 0; + transition: left 5s cubic-bezier(0, 0, 1, 1); + /* JavaScript sets left to 450px */ +} +``` + +...And how can we show a train slowing down? + +We can use another Bezier curve: `cubic-bezier(0.0, 0.5, 0.5 ,1.0)`. + +The graph: + +![](train-curve.png) + +As we can see, the process starts fast: the curve soars up high, and then slower and slower. + +Here's the timing function in action (click the train): + +[codetabs src="train"] + +CSS: +```css +.train { + left: 0; + transition: left 5s cubic-bezier(0, .5, .5, 1); + /* JavaScript sets left to 450px */ +} +``` + +There are several built-in curves: `linear`, `ease`, `ease-in`, `ease-out` and `ease-in-out`. + +The `linear` is a shorthand for `cubic-bezier(0, 0, 1, 1)` -- a straight line, we saw it already. + +Other names are shorthands for the following `cubic-bezier`: + +| ease* | ease-in | ease-out | ease-in-out | +|-------------------------------|----------------------|-----------------------|--------------------------| +| (0.25, 0.1, 0.25, 1.0) | (0.42, 0, 1.0, 1.0) | (0, 0, 0.58, 1.0) | (0.42, 0, 0.58, 1.0) | +| ![ease, figure](ease.png) | ![ease-in, figure](ease-in.png) | ![ease-out, figure](ease-out.png) | ![ease-in-out, figure](ease-in-out.png) | + +`*` -- by default, if there's no timing function, `ease` is used. + +So we could use `ease-out` for our slowing down train: + + +```css +.train { + left: 0; + transition: left 5s ease-out; + /* transition: left 5s cubic-bezier(0, .5, .5, 1); */ +} +``` + +But it looks a bit differently. + +**A Bezier curve can make the animation "jump out" of its range.** + +The control points on the curve can have any `y` coordinates: even negative or huge. Then the Bezier curve would also jump very low or high, making the animation go beyound its normal range. + +In the example below the animation code is: +```css +.train { + left: 100px; + transition: left 5s cubic-bezier(.5, -1, .5, 2); + /* JavaScript sets left to 400px */ +} +``` + +The property `left` should animate from `100px` to `400px`. + +But if you click the train, you'll see that: + +- First, the train goes *back*: `left` becomes less than `100px`. +- Then it goes forward, a little bit farther than `400px`. +- And then back again -- to `400px`. + +[codetabs src="train-over"] + +Why it happens -- pretty obvious if we look at the graph of the given Bezier curve: + +![](bezier-train-over.png) + +We moved the `y` coordinate of the 2nd point below zero, and for the 3rd point we made put it over `1`, so the curve goes out of the "regular" quadrant. The `y` is out of the "standard" range `0..1`. + +As we know, `y` measures "the completion of the animation process". The value `y = 0` corresponds to the starting property value and `y = 1` -- the ending value. So values `y<0` move the property lower than the starting `left` and `y>1` -- over the final `left`. + +That's a "soft" variant for sure. If we put `y` values like `-99` and `99` then the train would jump out of the range much more. + +But how to make the Bezier curve for a specific task? There are many tools. For instance, we can do it on the site . + +### Steps + +Timing function `steps(number of steps[, start/end])` allows to split animation into steps. + +Let's see that in an example with digits. We'll make the digits change not in a smooth, but in a discrete way. + +For that we split the animation into 9 steps: + +```css +#stripe.animate { + transform: translate(-90%); + transition: transform 9s *!*steps(9, start)*/!*; +} +``` + +In action `step(9, start)`: + +[codetabs src="step"] + +The first argument of `steps` is the number of steps. The transform will be split into 9 parts (10% each). The time interval is divided as well: 9 seconds split into 1 second intervals. + +The second argument is one of two words: `start` or `end`. + +The `start` means that in the beginning of animation we need to do make the first step immediately. + +We can observe that during the animation: when we click on the digit it changes to `1` (the first step) immediately, and then changes in the beginning of the next second. + +The process is progressing like this: + +- `0s` -- `-10%` (first change in the beginning of the 1st second, immediately) +- `1s` -- `-20%` +- ... +- `8s` -- `-80%` +- (the last second shows the final value). + +The alternative value `end` would mean that the change should be applied not in the beginning, but at the end of each second. + +So the process would go like this: + +- `0s` -- `0` +- `1s` -- `-10%` (first change at the end of the 1st second) +- `2s` -- `-20%` +- ... +- `9s` -- `-90%` + +In action `step(9, end)`: + +[codetabs src="step-end"] + +There are also shorthand values: + +- `step-start` -- is the same as `steps(1, start)`. That is, the animation starts immediately and takes 1 step. So it starts and finishes immediately, as if there were no animation. +- `step-end` -- the same as `steps(1, end)`: make the animation in a single step at the end of `transition-duration`. + +These values are rarely used, because that's not really animation, but rather a single-step change. + +## Event transitionend + +When the CSS animation finishes the `transitionend` event triggers. + +It is widely used to do an action after the animation is done. Also we can join animations. + +For instance, the ship in the example below starts to swim there and back on click, each time farther and farther to the right: + +[iframe src="boat" height=300 edit link] + +The animation is initiated by the function `go` that re-runs each time when the transition finishes and flips the direction: + +```js +boat.onclick = function() { + //... + let times = 1; + + function go() { + if (times % 2) { + // swim to the right + boat.classList.remove('back'); + boat.style.marginLeft = 100 * times + 200 + 'px'; + } else { + // swim to the left + boat.classList.add('back'); + boat.style.marginLeft = 100 * times - 200 + 'px'; + } + + } + + go(); + + boat.addEventListener('transitionend', function() { + times++; + go(); + }); +}; +``` + +The event object for `transitionend` has few specific properties: + +`event.propertyName` +: The property that has finished animating. Can be good if we animate multiple properties simultaneously. + +`event.elapsedTime` +: The time (in secods) that the animation took, without `transition-delay`. + +## Keyframes + +We can join multiple simple animations together using the `@keyframes` CSS rule. + +It specifies the "name" of the animation and rules: what, when and where to animate. Then using the `animation` property we attach the animation to the element and specify additional parameters for it. + +Here's an example with explanations: + +```html run height=60 autorun="no-epub" no-beautify +
+ + +``` + +There are many articles about `@keyframes` and a [detailed specification](https://drafts.csswg.org/css-animations/), so we won't go into more details here. + +Probably you won't need it often, unless everything is in the constant move on your sites. + +## Summary + +CSS animations allow to smoothly (or not) animate changes to one or multiple CSS properties. + +They are good for most animation tasks. We're also able to use JavaScript for animations, the next chapter is devoted to that. + +Limitations of CSS animations compared to JavaScript animations: + +```compare +- JavaScript animations are more flexible. They can implement any animation logic, like "explosion" of an element. We can create new elements in JavaScript for purposes of animation. ++ Simple things done simple. ++ Fast and easy for CPU. +``` + +The vast majority of animations uses the described CSS properties. And maybe the `transitionend` event to bind some JavaScript after it. + +But in the next chapter we'll do some JavaScript animations to cover more complex cases. diff --git a/5-animation/2-css-animations/bezier-linear.png b/5-animation/2-css-animations/bezier-linear.png new file mode 100644 index 00000000..795e4cdf Binary files /dev/null and b/5-animation/2-css-animations/bezier-linear.png differ diff --git a/5-animation/2-css-animations/bezier-linear@2x.png b/5-animation/2-css-animations/bezier-linear@2x.png new file mode 100644 index 00000000..95ec3cf9 Binary files /dev/null and b/5-animation/2-css-animations/bezier-linear@2x.png differ diff --git a/5-animation/2-css-animations/bezier-train-over.png b/5-animation/2-css-animations/bezier-train-over.png new file mode 100644 index 00000000..bd482290 Binary files /dev/null and b/5-animation/2-css-animations/bezier-train-over.png differ diff --git a/5-animation/2-css-animations/bezier-train-over@2x.png b/5-animation/2-css-animations/bezier-train-over@2x.png new file mode 100644 index 00000000..8dad7cc3 Binary files /dev/null and b/5-animation/2-css-animations/bezier-train-over@2x.png differ diff --git a/5-animation/2-css-transitions/boat.view/index.html b/5-animation/2-css-animations/boat.view/index.html similarity index 100% rename from 5-animation/2-css-transitions/boat.view/index.html rename to 5-animation/2-css-animations/boat.view/index.html diff --git a/5-animation/2-css-transitions/boat.view/style.css b/5-animation/2-css-animations/boat.view/style.css similarity index 100% rename from 5-animation/2-css-transitions/boat.view/style.css rename to 5-animation/2-css-animations/boat.view/style.css diff --git a/5-animation/2-css-transitions/digits-negative-delay.view/index.html b/5-animation/2-css-animations/digits-negative-delay.view/index.html similarity index 63% rename from 5-animation/2-css-transitions/digits-negative-delay.view/index.html rename to 5-animation/2-css-animations/digits-negative-delay.view/index.html index 15d26a7d..dbeefaae 100644 --- a/5-animation/2-css-transitions/digits-negative-delay.view/index.html +++ b/5-animation/2-css-animations/digits-negative-delay.view/index.html @@ -8,9 +8,9 @@ -
0123456789
+ Click below to animate: +
0123456789
- - \ No newline at end of file + diff --git a/5-animation/2-css-transitions/digits-negative-delay.view/script.js b/5-animation/2-css-animations/digits-negative-delay.view/script.js similarity index 100% rename from 5-animation/2-css-transitions/digits-negative-delay.view/script.js rename to 5-animation/2-css-animations/digits-negative-delay.view/script.js diff --git a/5-animation/2-css-animations/digits-negative-delay.view/style.css b/5-animation/2-css-animations/digits-negative-delay.view/style.css new file mode 100644 index 00000000..78c10f40 --- /dev/null +++ b/5-animation/2-css-animations/digits-negative-delay.view/style.css @@ -0,0 +1,17 @@ +#digit { + width: .5em; + overflow: hidden; + font: 32px monospace; + cursor: pointer; +} + +#stripe { + display: inline-block +} + +#stripe.animate { + transform: translate(-90%); + transition-property: transform; + transition-duration: 9s; + transition-timing-function: linear; +} diff --git a/5-animation/2-css-transitions/digits.view/index.html b/5-animation/2-css-animations/digits.view/index.html similarity index 63% rename from 5-animation/2-css-transitions/digits.view/index.html rename to 5-animation/2-css-animations/digits.view/index.html index 15d26a7d..a156d818 100644 --- a/5-animation/2-css-transitions/digits.view/index.html +++ b/5-animation/2-css-animations/digits.view/index.html @@ -8,9 +8,11 @@ -
0123456789
+ Click below to animate: + +
0123456789
- \ No newline at end of file + diff --git a/5-animation/2-css-transitions/digits.view/script.js b/5-animation/2-css-animations/digits.view/script.js similarity index 100% rename from 5-animation/2-css-transitions/digits.view/script.js rename to 5-animation/2-css-animations/digits.view/script.js diff --git a/5-animation/2-css-animations/digits.view/style.css b/5-animation/2-css-animations/digits.view/style.css new file mode 100644 index 00000000..78c10f40 --- /dev/null +++ b/5-animation/2-css-animations/digits.view/style.css @@ -0,0 +1,17 @@ +#digit { + width: .5em; + overflow: hidden; + font: 32px monospace; + cursor: pointer; +} + +#stripe { + display: inline-block +} + +#stripe.animate { + transform: translate(-90%); + transition-property: transform; + transition-duration: 9s; + transition-timing-function: linear; +} diff --git a/5-animation/2-css-animations/ease-in-out.png b/5-animation/2-css-animations/ease-in-out.png new file mode 100644 index 00000000..50ed8a7b Binary files /dev/null and b/5-animation/2-css-animations/ease-in-out.png differ diff --git a/5-animation/2-css-animations/ease-in-out@2x.png b/5-animation/2-css-animations/ease-in-out@2x.png new file mode 100644 index 00000000..067ad9ba Binary files /dev/null and b/5-animation/2-css-animations/ease-in-out@2x.png differ diff --git a/5-animation/2-css-animations/ease-in.png b/5-animation/2-css-animations/ease-in.png new file mode 100644 index 00000000..e00c52c4 Binary files /dev/null and b/5-animation/2-css-animations/ease-in.png differ diff --git a/5-animation/2-css-animations/ease-in@2x.png b/5-animation/2-css-animations/ease-in@2x.png new file mode 100644 index 00000000..14207250 Binary files /dev/null and b/5-animation/2-css-animations/ease-in@2x.png differ diff --git a/5-animation/2-css-animations/ease-out.png b/5-animation/2-css-animations/ease-out.png new file mode 100644 index 00000000..b95ce550 Binary files /dev/null and b/5-animation/2-css-animations/ease-out.png differ diff --git a/5-animation/2-css-animations/ease-out@2x.png b/5-animation/2-css-animations/ease-out@2x.png new file mode 100644 index 00000000..df4cca89 Binary files /dev/null and b/5-animation/2-css-animations/ease-out@2x.png differ diff --git a/5-animation/2-css-animations/ease.png b/5-animation/2-css-animations/ease.png new file mode 100644 index 00000000..2d4d91cd Binary files /dev/null and b/5-animation/2-css-animations/ease.png differ diff --git a/5-animation/2-css-animations/ease@2x.png b/5-animation/2-css-animations/ease@2x.png new file mode 100644 index 00000000..49eeb960 Binary files /dev/null and b/5-animation/2-css-animations/ease@2x.png differ diff --git a/5-animation/2-css-transitions/step-end.view/index.html b/5-animation/2-css-animations/step-end.view/index.html similarity index 71% rename from 5-animation/2-css-transitions/step-end.view/index.html rename to 5-animation/2-css-animations/step-end.view/index.html index 7dbe642c..2c8df727 100644 --- a/5-animation/2-css-transitions/step-end.view/index.html +++ b/5-animation/2-css-animations/step-end.view/index.html @@ -8,7 +8,9 @@ -
0123456789
+ Click below to animate: + +
0123456789
-``` - -Есть всего 5 свойств, задающих анимацию: - -- `transition-property` -- `transition-duration` -- `transition-timing-function` -- `transition-delay` - -Далее мы изучим их все, пока лишь заметим, что общее свойство `transition` может перечислять их все, в порядке: `property duration timing-function delay`, а также задавать анимацию нескольких свойств сразу. - -Например, при клике на эту кнопку анимируются одновременно цвет и размер шрифта: - -```html run height=80 autorun no-beautify - - - - - -``` - -Далее мы рассмотрим свойства анимации по отдельности. - -## transition-property - -Список свойств, которые будут анимироваться, например: `left`, `margin-left`, `height`, `color`. - -Анимировать можно не все свойства, но [многие](http://www.w3.org/TR/css3-transitions/#animatable-properties-). Значение `all` означает "анимировать все свойства". - -## transition-duration - -Продолжительность анимации, задаётся в формате [CSS time](http://www.w3.org/TR/css3-values/#time), то есть в секундах `s` или `ms`. - -## transition-delay - -Задержка до анимации. Например, если `transition-delay: 1s`, то анимация начнётся через 1 секунду после смены свойства. - -Возможны отрицательные значения, при этом анимация начнётся с середины. - -Например, вот анимация цифр от `0` до `9`: - -[codetabs src="digits"] - -Она осуществляется сменой `margin-left` у элемента с цифрами, примерно так: - -```css -#stripe.animate { - margin-left: -174px; - transition-property: margin-left; - transition-duration: 9s; -} -``` - -В примере выше JavaScript просто добавляет элементу класс -- и анимация стартует: - -```js -digit.classList.add('animate'); -``` - -Можно стартовать её "с середины", с нужной цифры, например соответствующей текущей секунде, при помощи отрицательного `transition-delay`. - -В примере ниже при клике на цифру она начнёт двигаться с текущей секунды: - -[codetabs src="digits-negative-delay"] - -В JavaScript это делается дополнительной строкой: - -```js -stripe.onclick = function() { - let sec = new Date().getSeconds() % 10; -*!* - // например, значение -3s начнёт анимацию с 3-й секунды - stripe.style.transitionDelay = '-' + sec + 's'; -*/!* - stripe.classList.add('animate'); -}; -``` - -## transition-timing-function - -Временнáя функция, которая задаёт, как процесс анимации будет распределён во времени, например начнётся ли анимация медленно, чтобы потом ускориться или наоборот. - -Самое сложное, но при небольшом изучении -- вполне очевидное свойство. - -У него есть два основных вида значения: кривая Безье и по шагам. Начнём с первого. - -### Кривая Безье - -В качестве временной функции можно выбрать любую [кривую Безье](/bezier) с 4 опорными точками, удовлетворяющую условиям: - -1. Начальная точка `(0,0)`. -2. Конечная точка `(1,1)`. -3. Для промежуточных точек значения `x` должны быть в интервале `0..1`, `y` -- любыми. - -Синтаксис для задания кривой Безье в CSS: `cubic-bezier(x2, y2, x3, y3)`. В нём указываются координаты только двух точек: второй и третьей, так как первая и последняя фиксированы. - -Она указывает, как быстро развивается процесс анимации во времени. - -- По оси `x` идёт время: `0` -- начальный момент, `1` -- конец времени `transition-duration`. -- По оси `y` -- завершённость процесса: `0` -- начальное значение анимируемого свойства, `1` -- конечное. - -Самый простой вариант -- это когда процесс развивается равномерно, "линейно" по времени. Это можно задать кривой Безье `cubic-bezier(0, 0, 1, 1)`. - -График этой "кривой" таков: - -![](bezier-linear.png) - -...Как видно, это просто прямая. По мере того, как проходит время `x`, завершённость анимации `y` равномерно приближается от `0` к `1`. - -Поезд в примере ниже с постоянной скоростью "едет" слева направо, используя такую временную функцию: - -[codetabs src="train-linear"] - -CSS для анимации: -```css -.train { - left: 0; - transition: left 5s cubic-bezier(0, 0, 1, 1); - /* JavaScript ставит значение left: 450px */ -} -``` - -Как нам показать, что поезд тормозит? - -Для этого используем кривую Безье: `cubic-bezier(0.0, 0.5, 0.5 ,1.0)`. - -График этой кривой: - -![](train-curve.png) - -Как видно, процесс вначале развивается быстро -- кривая резко идёт вверх, а затем всё медленнее, медленнее. - -Вы можете увидеть эту временную функцию в действии, кликнув на поезд: - -[codetabs src="train"] - -CSS для анимации: -```css -.train { - left: 0; - transition: left 5s cubic-bezier(0, .5, .5, 1); - /* JavaScript ставит значение left: 450px */ -} -``` - -Существует несколько стандартных обозначений кривых: `linear`, `ease`, `ease-in`, `ease-out` и `ease-in-out`. - -Значение `linear` -- это прямая, мы её уже видели. - -Остальные кривые являются короткой записью следующих `cubic-bezier`: - -| ease* | ease-in | ease-out | ease-in-out | -|-------------------------------|----------------------|-----------------------|--------------------------| -| (0.25, 0.1, 0.25, 1.0) | (0.42, 0, 1.0, 1.0) | (0, 0, 0.58, 1.0) | (0.42, 0, 0.58, 1.0) | -| ![ease, figure](ease.png) | ![ease-in, figure](ease-in.png) | ![ease-out, figure](ease-out.png) | ![ease-in-out, figure](ease-in-out.png) | - -`*` -- По умолчанию, если никакой временной функции не указано, используется `ease`. - -**Кривая Безье может заставить анимацию "выпрыгивать" за пределы диапазона.** - -Допустимо указывать для кривой Безье как отрицательные `y`, так и сколь угодно большие. При этом кривая Безье будет также по `y` выскакивать за пределы диапазона `0..1`, представляющего собой начало-конец значения. - -В примере ниже CSS-код анимации таков: -```css -.train { - left: 100px; - transition: left 5s cubic-bezier(.5, -1, .5, 2); - /* JavaScript поменяет left на 400px */ -} -``` - -Свойство `left` должно меняться от `100px` до `400px`. - -Однако, если кликнуть на поезд, то мы увидим, что: - -- Он едет сначала назад, то есть `left` становится меньше `100px`. -- Затем вперёд, причём выезжает за назначенные `400px`. -- А затем опять назад -- до `400px`. - -[codetabs src="train-over"] - -Почему так происходит -- отлично видно, если взглянуть на кривую Безье с указанными опорными точками: - -![](bezier-train-over.png) - -Мы вынесли координату `y` для второй опорной точки на 1 ниже нуля, а для третьей опорной точки -- на 1 выше единицы, поэтому и кривая вышла за границы "обычного" квадрата. Её значения по `y` вышли из стандартного диапазона `0..1`. - -Как мы помним, значению `y = 0` соответствует "нулевое" положение анимации, а `y = 1` -- конечное. Получается, что значения `y<0` двинули поезд назад, меньше исходного `left`, а значения `y>1` -- больше итогового `left`. - -Это, конечно, "мягкий" вариант. Если поставить значения `y` порядка `-99`, `99`, то поезд будет куда более сильно выпрыгивать за диапазон. - -Итак, кривая Безье позволяет задавать "плавное"" течение анимации. Подобрать кривую Безье вручную можно на сайте . - -### Шаги steps - -Временная функция `steps(количество шагов[, start/end])` позволяет разбить анимацию на чёткое количество шагов. - -Проще всего это увидеть на примере. Выше мы видели плавную анимацию цифр от `0` до `9` при помощи смены `margin-left` у элемента, содержащего `0123456789`. - -Чтобы цифры сдвигались не плавно, а шли чётко и раздельно, одна за другой -- мы разобьём анимацию на 9 шагов: -```css -#stripe.animate { - margin-left: -174px; - transition: margin-left 9s *!*steps(9, start)*/!*; -} -``` - -В действии `step(9, start)`: - -[codetabs src="step"] - -Первый аргумент `steps` -- количество шагов, то есть изменение `margin-left` разделить на 9 частей, получается примерно по `19px`. На то же количество частей делится и временной интервал, то есть по `1s`. - -`start` -- означает, что при начале анимации нужно сразу применить первое изменение. Это проявляется тем, что при нажатии на цифру она меняется на `1` (первое изменение `margin-left`) мгновенно, а затем в начале каждой следующей секунды. - -То есть, процесс развивается так: - -- `0s` -- `-19px` (первое изменение в начале 1-й секунды, сразу при нажатии) -- `1s` -- `-38px` -- ... -- `8s` -- `-174px` -- (на протяжении последней секунды видно окончательное значение). - -Альтернативное значение `end` означало бы, что изменения нужно применять не в начале, а в конце каждой секунды, то есть так: - -- `0s` -- `0` -- `1s` -- `-19px` (первое изменение в конце 1-й секунды) -- `2s` -- `-38px` -- ... -- `9s` -- `-174px` - -В действии `step(9, end)`: - -[codetabs src="step-end"] - -Также есть сокращённые значения: - -- `step-start` -- то же, что `steps(1, start)`, то есть завершить анимацию в 1 шаг сразу. -- `step-end` -- то же, что `steps(1, end)`, то есть завершить анимацию в 1 шаг по истечении `transition-duration`. - -Такие значения востребованы редко, так как это даже и не анимация почти, но тоже бывают полезны. - -## Событие transitionend - -На конец CSS-анимации можно повесить обработчик на событие `transitionend`. - -Это широко используется, чтобы после анимации сделать какое-то действие или объединить несколько анимаций в одну. - -Например, лодочка в примере ниже при клике начинает плавать туда-обратно, с каждым разом уплывая всё дальше вправо: - -[iframe src="boat" height=300 edit link] - -Её анимация осуществляется функцией `go`, которая перезапускается по окончании, с переворотом через CSS: - -```js -boat.onclick = function() { - //... - let times = 1; - - function go() { - if (times % 2) { - // плывём вправо - boat.classList.remove('back'); - boat.style.marginLeft = 100 * times + 200 + 'px'; - } else { - // плывём влево - boat.classList.add('back'); - boat.style.marginLeft = 100 * times - 200 + 'px'; - } - - } - - go(); - - boat.addEventListener('transitionend', function() { - times++; - go(); - }); -}; -``` - -Объект события `transitionend` содержит специфические свойства: - -`propertyName` -: Свойство, анимация которого завершилась. - -`elapsedTime` -: Время (в секундах), которое заняла анимация, без учета `transition-delay`. - -Свойство `propertyName` может быть полезно при одновременной анимации нескольких свойств. Каждое свойство даст своё событие, и можно решить, что с ним делать дальше. - -## CSS animations - -Более сложные анимации делаются объединением простых при помощи CSS-правила `@keyframes`. - -В нём задаётся "имя" анимации и правила: что, откуда и куда анимировать. Затем при помощи свойства `animation: имя параметры` эта анимация подключается к элементу, задаётся время анимации и дополнительные параметры, как её применять. - -Пример с пояснениями в комментарии: - -```html run height=60 autorun="no-epub" no-beautify -
- - -``` - -Этот стандарт пока в черновике, поэтому в Chrome, Safari, Opera нужен префикс `-webkit`. - -Статей про CSS animations достаточно много, посмотрите, например: - -- [Статья про CSS Animation](http://css.yoksel.ru/css-animation/). -- [Пример бесконечной подпрыгивающей анимации на CSS Animation и кривых Безье](https://albiebrown.github.io/gravify/). - -## Итого - -CSS-анимации позволяют плавно или не очень менять одно или несколько свойств. - -Альтернатива им -- плавное изменение значений свойств через JavaScript, мы рассмотрим подробности далее. - -Ограничения и достоинства CSS-анимаций по сравнению с JavaScript: - -```compare -- Временная функция может быть задана кривой Безье или через шаги. Более сложные анимации, состоящие из нескольких кривых, реализуются их комбинацией при помощи [CSS animations](http://www.w3.org/TR/css3-animations/), но JavaScript-функции всегда гибче. -- CSS-анимации касаются только свойств, а в JavaScript можно делать всё, что угодно, удалять элементы, создавать новые. -- Отсутствует поддержка в IE9- -+ Простые вещи делаются просто. -+ "Легче" для процессора, чем анимации JavaScript, лучше используется графический ускоритель. Это очень важно для мобильных устройств. -``` - -Подавляющее большинство анимаций делается через CSS. - -При этом JavaScript запускает их начало -- как правило, добавлением класса, в котором задано новое свойство, и может отследить окончание через событие `transitionend`. diff --git a/5-animation/2-css-transitions/bezier-linear.png b/5-animation/2-css-transitions/bezier-linear.png deleted file mode 100644 index c34c974a..00000000 Binary files a/5-animation/2-css-transitions/bezier-linear.png and /dev/null differ diff --git a/5-animation/2-css-transitions/bezier-linear@2x.png b/5-animation/2-css-transitions/bezier-linear@2x.png deleted file mode 100644 index 9f5631a3..00000000 Binary files a/5-animation/2-css-transitions/bezier-linear@2x.png and /dev/null differ diff --git a/5-animation/2-css-transitions/bezier-train-over.png b/5-animation/2-css-transitions/bezier-train-over.png deleted file mode 100644 index fff851cb..00000000 Binary files a/5-animation/2-css-transitions/bezier-train-over.png and /dev/null differ diff --git a/5-animation/2-css-transitions/bezier-train-over@2x.png b/5-animation/2-css-transitions/bezier-train-over@2x.png deleted file mode 100644 index b065b0f1..00000000 Binary files a/5-animation/2-css-transitions/bezier-train-over@2x.png and /dev/null differ diff --git a/5-animation/2-css-transitions/digits-negative-delay.view/style.css b/5-animation/2-css-transitions/digits-negative-delay.view/style.css deleted file mode 100644 index a3e25cf4..00000000 --- a/5-animation/2-css-transitions/digits-negative-delay.view/style.css +++ /dev/null @@ -1,12 +0,0 @@ -#digit { - width: .5em; - overflow: hidden; - font: 32px "Courier New", monospace; -} - -#stripe.animate { - margin-left: -174px; - transition-property: margin-left; - transition-duration: 9s; - transition-timing-function: linear; -} \ No newline at end of file diff --git a/5-animation/2-css-transitions/digits.view/style.css b/5-animation/2-css-transitions/digits.view/style.css deleted file mode 100644 index a3e25cf4..00000000 --- a/5-animation/2-css-transitions/digits.view/style.css +++ /dev/null @@ -1,12 +0,0 @@ -#digit { - width: .5em; - overflow: hidden; - font: 32px "Courier New", monospace; -} - -#stripe.animate { - margin-left: -174px; - transition-property: margin-left; - transition-duration: 9s; - transition-timing-function: linear; -} \ No newline at end of file diff --git a/5-animation/2-css-transitions/ease-in-out.png b/5-animation/2-css-transitions/ease-in-out.png deleted file mode 100644 index 896d853a..00000000 Binary files a/5-animation/2-css-transitions/ease-in-out.png and /dev/null differ diff --git a/5-animation/2-css-transitions/ease-in-out@2x.png b/5-animation/2-css-transitions/ease-in-out@2x.png deleted file mode 100644 index 6c6bcd74..00000000 Binary files a/5-animation/2-css-transitions/ease-in-out@2x.png and /dev/null differ diff --git a/5-animation/2-css-transitions/ease-in.png b/5-animation/2-css-transitions/ease-in.png deleted file mode 100644 index e2020c20..00000000 Binary files a/5-animation/2-css-transitions/ease-in.png and /dev/null differ diff --git a/5-animation/2-css-transitions/ease-in@2x.png b/5-animation/2-css-transitions/ease-in@2x.png deleted file mode 100644 index 2696a033..00000000 Binary files a/5-animation/2-css-transitions/ease-in@2x.png and /dev/null differ diff --git a/5-animation/2-css-transitions/ease-out.png b/5-animation/2-css-transitions/ease-out.png deleted file mode 100644 index 9ee15054..00000000 Binary files a/5-animation/2-css-transitions/ease-out.png and /dev/null differ diff --git a/5-animation/2-css-transitions/ease-out@2x.png b/5-animation/2-css-transitions/ease-out@2x.png deleted file mode 100644 index 8dba43f7..00000000 Binary files a/5-animation/2-css-transitions/ease-out@2x.png and /dev/null differ diff --git a/5-animation/2-css-transitions/ease.png b/5-animation/2-css-transitions/ease.png deleted file mode 100644 index 9f8e2752..00000000 Binary files a/5-animation/2-css-transitions/ease.png and /dev/null differ diff --git a/5-animation/2-css-transitions/ease@2x.png b/5-animation/2-css-transitions/ease@2x.png deleted file mode 100644 index ee540fab..00000000 Binary files a/5-animation/2-css-transitions/ease@2x.png and /dev/null differ diff --git a/5-animation/2-css-transitions/step-end.view/style.css b/5-animation/2-css-transitions/step-end.view/style.css deleted file mode 100644 index 30741ad4..00000000 --- a/5-animation/2-css-transitions/step-end.view/style.css +++ /dev/null @@ -1,12 +0,0 @@ -#digit { - width: .5em; - overflow: hidden; - font: 32px "Courier New", monospace; -} - -#stripe.animate { - margin-left: -174px; - transition-property: margin-left; - transition-duration: 9s; - transition-timing-function: steps(9, end); -} \ No newline at end of file diff --git a/5-animation/2-css-transitions/step.view/style.css b/5-animation/2-css-transitions/step.view/style.css deleted file mode 100644 index e4583b34..00000000 --- a/5-animation/2-css-transitions/step.view/style.css +++ /dev/null @@ -1,12 +0,0 @@ -#digit { - width: .5em; - overflow: hidden; - font: 32px "Courier New", monospace; -} - -#stripe.animate { - margin-left: -174px; - transition-property: margin-left; - transition-duration: 9s; - transition-timing-function: steps(9, start); -} \ No newline at end of file diff --git a/5-animation/2-css-transitions/train-curve.png b/5-animation/2-css-transitions/train-curve.png deleted file mode 100644 index 230f82ef..00000000 Binary files a/5-animation/2-css-transitions/train-curve.png and /dev/null differ diff --git a/5-animation/2-css-transitions/train-curve@2x.png b/5-animation/2-css-transitions/train-curve@2x.png deleted file mode 100644 index e7dabcf6..00000000 Binary files a/5-animation/2-css-transitions/train-curve@2x.png and /dev/null differ diff --git a/5-animation/3-js-animation/article.md b/5-animation/3-js-animation/article.md index 0dc9389a..dc80e1fb 100644 --- a/5-animation/3-js-animation/article.md +++ b/5-animation/3-js-animation/article.md @@ -1,97 +1,108 @@ -# JS-Анимация +# JavaScript animations [todo] -JavaScript-анимация применяется там, где не подходит CSS. +JavaScript animations can handle things that CSS can't. -Например, по сложной траектории, с временной функцией, выходящей за рамки кривых Безье, на canvas. Иногда её используют для анимации в старых IE. +For instance, moving along a complex path, with a timing function different from Bezier curves, or an animation on a canvas. [cut] ## setInterval -С точки зрения HTML/CSS, анимация -- это постепенное изменение стиля DOM-элемента. Например, увеличение координаты `style.left` от `0px` до `100px` сдвигает элемент. +From the HTML/CSS point of view, an animation is a gradual change of the style property. For instance, changing `style.left` from `0px` to `100px` moves the element. -Если увеличивать `left` от `0` до `100` при помощи `setInterval`, делая по 50 изменений в секунду, то это будет выглядеть как плавное перемещение. Тот же принцип, что и в кино: для непрерывной анимации достаточно 24 или больше вызовов `setInterval` в секунду. +And if we increase it in `setInterval`, by making 50 small changes per second, then it looks smooth. That's the same principle as in the cinema: 24 or more frames per second is enough to make it look smooth. -Псевдо-код для анимации выглядит так: +The pseudo-code can look like this: ```js -let fps = 50; // 50 кадров в секунду +let fps = 50; // 50 frames per second let timer = setInterval(function() { - if (время вышло) clearInterval(timer); - else немного увеличить left + if (animation complete) clearInterval(timer); + else increase style.left }, 1000 / fps) ``` +The more complete example of the animation: Более полный пример кода анимации: ```js -let start = Date.now(); // сохранить время начала +let start = Date.now(); // remember start time let timer = setInterval(function() { - // вычислить сколько времени прошло с начала анимации + // how much time passed from the start? let timePassed = Date.now() - start; if (timePassed >= 2000) { - clearInterval(timer); // конец через 2 секунды + clearInterval(timer); // finish the animation after 2 seconds return; } - // рисует состояние анимации, соответствующее времени timePassed + // draw the animation at the moment timePassed draw(timePassed); }, 20); -// в то время как timePassed идёт от 0 до 2000 -// left принимает значения от 0 до 400px +// as timePassed goes from 0 to 2000 +// left gets values from 0px to 400px function draw(timePassed) { train.style.left = timePassed / 5 + 'px'; } ``` -Кликните для демонстрации: +Click for the demo: [codetabs height=200 src="move"] ## requestAnimationFrame -Если у нас не один такой `setInterval`, а несколько в разных местах кода, то браузеру нужно в те же 20 мс работать со страницей уже несколько раз. А ведь кроме `setInterval` есть ещё другие действия, к примеру, прокрутка страницы, которую тоже надо нарисовать. +Let's imagine we have several simultaneous animations. -Если все действия по перерисовке производить независимо, то будет выполняться много двойной работы. +If we run them separately, each one with its own `setInterval(..., 20)`, then the browser would have to repaint much more often than every `20ms`. -Гораздо выгоднее с точки зрения производительности -- сгруппировать все перерисовки в одну и запускать их централизованно, все вместе. +Each `setInterval` triggers once per `20ms`, but they are independent, so we have several independent runs within `20ms`. -Для этого в JavaScript-фреймворках, которые поддерживают анимацию, есть единый таймер: +These several independant actions should be grouped together, because it's easier for the browser to redraw things once per `20ms`. + +In other words, this: ```js setInterval(function() { - /* отрисовать все анимации */ -}, 20); + animate1(); + animate2(); + animate3(); +}, 20) ``` -...Все анимации, которые запускает такой фреймворк, добавляются в общий список, и раз в 20 мс единый таймер проверяет его, запускает текущие, удаляет завершившиеся. +...Is lighter than this: -Современные браузеры, кроме IE9-, поддерживают стандарт [Animation timing](http://www.w3.org/TR/animation-timing/), который представляет собой дальнейший шаг в этом направлении. Он позволяет синхронизировать наши анимации со встроенными механизмами обновления страницы. То есть, сгруппированы будут не только наши, но и CSS-анимации и другие браузерные перерисовки. +```js +setInterval(animate1, 20); +setInterval(animate2, 20); +setInterval(animate3, 20); +``` -При этом графический ускоритель будет использован максимально эффективно, и исключена повторная обработка одних и тех же участков страницы. А значит -- меньше будет загрузка CPU, да и сама анимация станет более плавной. +There's one more thing to keep in mind. Sometimes when CPU is overloaded or for other reasons it may be better to trigger redraws less often. Not 20, but maybe 200ms. -Для этого используется функция [requestAnimationFrame](http://www.w3.org/TR/animation-timing/#dom-windowanimationtiming-requestanimationframe). +There's a standard [Animation timing](http://www.w3.org/TR/animation-timing/) that provides the function `requestAnimationFrame`. -Синтаксис: +It addresses all those issues and even more. + +The syntax: ```js let requestId = requestAnimationFrame(callback) ``` -Такой вызов планирует запуск `callback` в ближайшее время, когда браузер сочтёт возможным осуществить анимацию. +That schedules the `callback` function to run in the closest time when the browser wants to do animation. -Если запланировать в `callback` какое-то рисование, то оно будет сгруппировано с другими `requestAnimationFrame` и с внутренними перерисовками браузера. +If we do changes in elements in `callback` then they will be grouped together with other `requestAnimationFrame` callbacks and with CSS animations. So there will be one repaint instead of many. -Возвращаемое значение `requestId` служит для отмены запуска: +The returned value `requestId` can be used to cancel the call: ```js -// отменить запланированное выше выполнение callback +// cancel the scheduled execution of callback cancelAnimationFrame(requestId); ``` -Функция `callback` получает один аргумент -- время, прошедшее с начала загрузки страницы, результат вызова [performance.now()](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now). +The `callback` function получает один аргумент -- время, прошедшее с начала загрузки страницы, результат вызова [performance.now()](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now). Как правило, запуск `callback` происходит очень скоро. Если у процессора большая загрузка или батарея у ноутбука почти разряжена -- то пореже. @@ -493,4 +504,3 @@ function animate(options) { - Нестандартные задачи и требования, не укладывающиеся в рамки CSS. - Поддержка IE9-. - Графика, рисование на canvas. - diff --git a/5-animation/3-js-animation/back.png b/5-animation/3-js-animation/back.png index 04246bed..c63bc9d9 100644 Binary files a/5-animation/3-js-animation/back.png and b/5-animation/3-js-animation/back.png differ diff --git a/5-animation/3-js-animation/back@2x.png b/5-animation/3-js-animation/back@2x.png index 6d4f318d..794f1623 100644 Binary files a/5-animation/3-js-animation/back@2x.png and b/5-animation/3-js-animation/back@2x.png differ diff --git a/5-animation/3-js-animation/bezier-linear.png b/5-animation/3-js-animation/bezier-linear.png index c34c974a..795e4cdf 100644 Binary files a/5-animation/3-js-animation/bezier-linear.png and b/5-animation/3-js-animation/bezier-linear.png differ diff --git a/5-animation/3-js-animation/bezier-linear@2x.png b/5-animation/3-js-animation/bezier-linear@2x.png index 9f5631a3..95ec3cf9 100644 Binary files a/5-animation/3-js-animation/bezier-linear@2x.png and b/5-animation/3-js-animation/bezier-linear@2x.png differ diff --git a/5-animation/3-js-animation/bounce-inout.png b/5-animation/3-js-animation/bounce-inout.png index d6b8624f..af1e90d7 100644 Binary files a/5-animation/3-js-animation/bounce-inout.png and b/5-animation/3-js-animation/bounce-inout.png differ diff --git a/5-animation/3-js-animation/bounce-inout@2x.png b/5-animation/3-js-animation/bounce-inout@2x.png index 2c440c72..1c558f46 100644 Binary files a/5-animation/3-js-animation/bounce-inout@2x.png and b/5-animation/3-js-animation/bounce-inout@2x.png differ diff --git a/5-animation/3-js-animation/circ-ease.png b/5-animation/3-js-animation/circ-ease.png index 528cd44c..657942f7 100644 Binary files a/5-animation/3-js-animation/circ-ease.png and b/5-animation/3-js-animation/circ-ease.png differ diff --git a/5-animation/3-js-animation/circ-ease@2x.png b/5-animation/3-js-animation/circ-ease@2x.png index a8f352d8..9f68a73f 100644 Binary files a/5-animation/3-js-animation/circ-ease@2x.png and b/5-animation/3-js-animation/circ-ease@2x.png differ diff --git a/5-animation/3-js-animation/circ.png b/5-animation/3-js-animation/circ.png index 9f81aae2..cdb43f79 100644 Binary files a/5-animation/3-js-animation/circ.png and b/5-animation/3-js-animation/circ.png differ diff --git a/5-animation/3-js-animation/circ@2x.png b/5-animation/3-js-animation/circ@2x.png index 0a5d7934..7d1c7ced 100644 Binary files a/5-animation/3-js-animation/circ@2x.png and b/5-animation/3-js-animation/circ@2x.png differ diff --git a/5-animation/3-js-animation/elastic.png b/5-animation/3-js-animation/elastic.png index beb005be..f18ffbdc 100644 Binary files a/5-animation/3-js-animation/elastic.png and b/5-animation/3-js-animation/elastic.png differ diff --git a/5-animation/3-js-animation/elastic@2x.png b/5-animation/3-js-animation/elastic@2x.png index 3fc29724..2dbd6d3c 100644 Binary files a/5-animation/3-js-animation/elastic@2x.png and b/5-animation/3-js-animation/elastic@2x.png differ diff --git a/5-animation/3-js-animation/linear.png b/5-animation/3-js-animation/linear.png index 748d4064..9d29ec1b 100644 Binary files a/5-animation/3-js-animation/linear.png and b/5-animation/3-js-animation/linear.png differ diff --git a/5-animation/3-js-animation/linear@2x.png b/5-animation/3-js-animation/linear@2x.png index 4462b35b..e10b7fef 100644 Binary files a/5-animation/3-js-animation/linear@2x.png and b/5-animation/3-js-animation/linear@2x.png differ diff --git a/5-animation/3-js-animation/quad.png b/5-animation/3-js-animation/quad.png index 6b16994d..670715a7 100644 Binary files a/5-animation/3-js-animation/quad.png and b/5-animation/3-js-animation/quad.png differ diff --git a/5-animation/3-js-animation/quad@2x.png b/5-animation/3-js-animation/quad@2x.png index 61407a1a..9a3ca207 100644 Binary files a/5-animation/3-js-animation/quad@2x.png and b/5-animation/3-js-animation/quad@2x.png differ diff --git a/5-animation/3-js-animation/quint.png b/5-animation/3-js-animation/quint.png index 5f480026..35c06319 100644 Binary files a/5-animation/3-js-animation/quint.png and b/5-animation/3-js-animation/quint.png differ diff --git a/5-animation/3-js-animation/quint@2x.png b/5-animation/3-js-animation/quint@2x.png index 44f1e0ad..d3477022 100644 Binary files a/5-animation/3-js-animation/quint@2x.png and b/5-animation/3-js-animation/quint@2x.png differ diff --git a/figures.sketch b/figures.sketch index d2a41958..8728ddcd 100644 Binary files a/figures.sketch and b/figures.sketch differ