From 11f2d7352f7a3c69ce65584595e97d8064880078 Mon Sep 17 00:00:00 2001 From: Ilya Kantor Date: Wed, 25 Feb 2015 14:42:09 +0300 Subject: [PATCH] renovations --- 3-more/2-animation/2-bezier/demo.svg | 1 - 3-more/2-animation/index.md | 2 - .../1-bezier}/article.md | 97 ++++---- .../1-bezier}/bezier2.png | Bin .../1-bezier}/bezier3-draw1.png | Bin .../1-bezier}/bezier3-draw2.png | Bin .../1-bezier}/bezier3-e.png | Bin .../1-bezier}/bezier3.png | Bin .../1-bezier}/bezier4-e.png | Bin .../1-bezier}/bezier4.png | Bin .../2-bezier => 3-animation/1-bezier}/car.jpg | Bin 3-more/3-animation/1-bezier/demo.svg | 1 + .../1-bezier}/letter_m.png | Bin 3-more/3-animation/1-bezier/play.png | Bin 0 -> 4702 bytes .../1-bezier}/vase.png | Bin .../1-animate-logo-css/solution.md | 0 .../solution.view/index.html | 0 .../source.view}/animate.js | 0 .../source.view/index.html | 0 .../1-animate-logo-css/task.md | 0 .../2-css-transitions}/article.md | 68 +----- .../2-css-transitions}/boat.view/index.html | 0 .../2-css-transitions}/ease-in-out.png | Bin .../2-css-transitions}/ease-in.png | Bin .../2-css-transitions}/ease-out.png | Bin .../2-css-transitions}/ease.png | Bin .../2-css-transitions}/train-curve.png | Bin .../1-carousel-animated/solution.md | 0 .../solution.view/animate.js | 0 .../solution.view/index.html | 0 .../solution.view/style.css | 0 .../1-carousel-animated/task.md | 0 .../2-animate-logo/solution.md | 0 .../2-animate-logo/solution.view}/animate.js | 0 .../2-animate-logo/solution.view/index.html | 0 .../2-animate-logo}/source.view/animate.js | 0 .../2-animate-logo}/source.view/index.html | 0 .../3-js-animation}/2-animate-logo/task.md | 0 .../3-animate-ball/solution.md | 0 .../3-animate-ball/solution.view/animate.js | 0 .../3-animate-ball/solution.view/index.html | 0 .../3-animate-ball/source.view/animate.js | 0 .../3-animate-ball/source.view/index.html | 0 .../3-js-animation}/3-animate-ball/task.md | 0 .../4-animate-ball-hops/solution.md | 0 .../solution.view/animate.js | 0 .../solution.view/index.html | 0 .../source.view/animate.js | 0 .../source.view/index.html | 0 .../4-animate-ball-hops/task.md | 0 .../3-js-animation}/article.md | 0 .../3-js-animation}/back.svg | 0 .../3-js-animation}/bounce-inout.svg | 0 .../3-js-animation}/circ-ease.svg | 0 .../3-js-animation}/circ.svg | 0 .../3-js-animation}/elastic.svg | 0 .../3-js-animation}/linear.svg | 0 .../3-js-animation}/move.view/index.html | 0 .../3-js-animation}/move100.view/index.html | 0 .../3-js-animation}/quad.svg | 0 .../3-js-animation}/quint.svg | 0 .../3-js-animation}/width.view/index.html | 0 3-more/3-animation/index.md | 3 + 3-more/4-optimize/1-memory-leaks/article.md | 217 +++--------------- .../1-memory-leaks/leak-ie8-2.view/index.html | 32 +++ .../leak-ie8-table.view/index.html | 33 +++ .../leak-ie8-widget.view/index.html | 38 +++ .../leak-ie8-xhr.view/index.html | 35 +++ .../1-memory-leaks/leak-ie8.view/index.html | 36 +++ .../2-memory-leaks-jquery/article.md | 125 ++++++++++ .../jquery-leak.view/index.html | 32 +++ .../3-minification}/article.md | 0 .../3-minification}/my.svg | 0 .../4-better-minification}/article.md | 34 +-- .../5-gcc-advanced-optimization}/article.md | 0 .../6-gcc-check-types}/article.md | 0 .../7-gcc-closure-library}/article.md | 0 3-more/4-optimize/index.md | 2 + 3-more/5-compress/index.md | 2 - .../3-reflow/article.md | 0 .../3-reflow/reflow.view/index.html | 0 .../4-script-place-optimize}/article.md | 0 82 files changed, 437 insertions(+), 321 deletions(-) delete mode 100755 3-more/2-animation/2-bezier/demo.svg delete mode 100644 3-more/2-animation/index.md rename 3-more/{2-animation/2-bezier => 3-animation/1-bezier}/article.md (62%) rename 3-more/{2-animation/2-bezier => 3-animation/1-bezier}/bezier2.png (100%) mode change 100755 => 100644 rename 3-more/{2-animation/2-bezier => 3-animation/1-bezier}/bezier3-draw1.png (100%) mode change 100755 => 100644 rename 3-more/{2-animation/2-bezier => 3-animation/1-bezier}/bezier3-draw2.png (100%) mode change 100755 => 100644 rename 3-more/{2-animation/2-bezier => 3-animation/1-bezier}/bezier3-e.png (100%) mode change 100755 => 100644 rename 3-more/{2-animation/2-bezier => 3-animation/1-bezier}/bezier3.png (100%) mode change 100755 => 100644 rename 3-more/{2-animation/2-bezier => 3-animation/1-bezier}/bezier4-e.png (100%) mode change 100755 => 100644 rename 3-more/{2-animation/2-bezier => 3-animation/1-bezier}/bezier4.png (100%) mode change 100755 => 100644 rename 3-more/{2-animation/2-bezier => 3-animation/1-bezier}/car.jpg (100%) mode change 100755 => 100644 create mode 100644 3-more/3-animation/1-bezier/demo.svg rename 3-more/{2-animation/2-bezier => 3-animation/1-bezier}/letter_m.png (100%) mode change 100755 => 100644 create mode 100644 3-more/3-animation/1-bezier/play.png rename 3-more/{2-animation/2-bezier => 3-animation/1-bezier}/vase.png (100%) mode change 100755 => 100644 rename 3-more/{2-animation/3-css-animation => 3-animation/2-css-transitions}/1-animate-logo-css/solution.md (100%) rename 3-more/{2-animation/3-css-animation => 3-animation/2-css-transitions}/1-animate-logo-css/solution.view/index.html (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation/1-carousel-animated/solution.view => 3-animation/2-css-transitions/1-animate-logo-css/source.view}/animate.js (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation/2-animate-logo => 3-animation/2-css-transitions/1-animate-logo-css}/source.view/index.html (100%) mode change 100755 => 100644 rename 3-more/{2-animation/3-css-animation => 3-animation/2-css-transitions}/1-animate-logo-css/task.md (100%) rename 3-more/{2-animation/3-css-animation => 3-animation/2-css-transitions}/article.md (78%) rename 3-more/{2-animation/3-css-animation => 3-animation/2-css-transitions}/boat.view/index.html (100%) mode change 100755 => 100644 rename 3-more/{2-animation/3-css-animation => 3-animation/2-css-transitions}/ease-in-out.png (100%) mode change 100755 => 100644 rename 3-more/{2-animation/3-css-animation => 3-animation/2-css-transitions}/ease-in.png (100%) mode change 100755 => 100644 rename 3-more/{2-animation/3-css-animation => 3-animation/2-css-transitions}/ease-out.png (100%) mode change 100755 => 100644 rename 3-more/{2-animation/3-css-animation => 3-animation/2-css-transitions}/ease.png (100%) mode change 100755 => 100644 rename 3-more/{2-animation/3-css-animation => 3-animation/2-css-transitions}/train-curve.png (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/1-carousel-animated/solution.md (100%) rename 3-more/{2-animation/1-js-animation/2-animate-logo => 3-animation/3-js-animation/1-carousel-animated}/solution.view/animate.js (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/1-carousel-animated/solution.view/index.html (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/1-carousel-animated/solution.view/style.css (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/1-carousel-animated/task.md (100%) rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/2-animate-logo/solution.md (100%) rename 3-more/{2-animation/1-js-animation/2-animate-logo/source.view => 3-animation/3-js-animation/2-animate-logo/solution.view}/animate.js (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/2-animate-logo/solution.view/index.html (100%) mode change 100755 => 100644 rename 3-more/{2-animation/3-css-animation/1-animate-logo-css => 3-animation/3-js-animation/2-animate-logo}/source.view/animate.js (100%) mode change 100755 => 100644 rename 3-more/{2-animation/3-css-animation/1-animate-logo-css => 3-animation/3-js-animation/2-animate-logo}/source.view/index.html (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/2-animate-logo/task.md (100%) rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/3-animate-ball/solution.md (100%) rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/3-animate-ball/solution.view/animate.js (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/3-animate-ball/solution.view/index.html (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/3-animate-ball/source.view/animate.js (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/3-animate-ball/source.view/index.html (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/3-animate-ball/task.md (100%) rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/4-animate-ball-hops/solution.md (100%) rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/4-animate-ball-hops/solution.view/animate.js (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/4-animate-ball-hops/solution.view/index.html (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/4-animate-ball-hops/source.view/animate.js (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/4-animate-ball-hops/source.view/index.html (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/4-animate-ball-hops/task.md (100%) rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/article.md (100%) rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/back.svg (100%) rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/bounce-inout.svg (100%) rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/circ-ease.svg (100%) rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/circ.svg (100%) rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/elastic.svg (100%) rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/linear.svg (100%) rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/move.view/index.html (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/move100.view/index.html (100%) mode change 100755 => 100644 rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/quad.svg (100%) rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/quint.svg (100%) rename 3-more/{2-animation/1-js-animation => 3-animation/3-js-animation}/width.view/index.html (100%) mode change 100755 => 100644 create mode 100644 3-more/3-animation/index.md create mode 100644 3-more/4-optimize/1-memory-leaks/leak-ie8-2.view/index.html create mode 100644 3-more/4-optimize/1-memory-leaks/leak-ie8-table.view/index.html create mode 100644 3-more/4-optimize/1-memory-leaks/leak-ie8-widget.view/index.html create mode 100644 3-more/4-optimize/1-memory-leaks/leak-ie8-xhr.view/index.html create mode 100644 3-more/4-optimize/1-memory-leaks/leak-ie8.view/index.html create mode 100644 3-more/4-optimize/2-memory-leaks-jquery/article.md create mode 100644 3-more/4-optimize/2-memory-leaks-jquery/jquery-leak.view/index.html rename 3-more/{5-compress/1-minification => 4-optimize/3-minification}/article.md (100%) rename 3-more/{5-compress/1-minification => 4-optimize/3-minification}/my.svg (100%) mode change 100755 => 100644 rename 3-more/{5-compress/2-better-minification => 4-optimize/4-better-minification}/article.md (76%) rename 3-more/{5-compress/3-gcc-advanced-optimization => 4-optimize/5-gcc-advanced-optimization}/article.md (100%) rename 3-more/{5-compress/4-gcc-check-types => 4-optimize/6-gcc-check-types}/article.md (100%) rename 3-more/{5-compress/5-gcc-closure-library => 4-optimize/7-gcc-closure-library}/article.md (100%) delete mode 100644 3-more/5-compress/index.md rename {3-more/4-optimize => archive}/3-reflow/article.md (100%) rename {3-more/4-optimize => archive}/3-reflow/reflow.view/index.html (100%) mode change 100755 => 100644 rename {3-more/4-optimize/2-script-place-optimize => archive/4-script-place-optimize}/article.md (100%) diff --git a/3-more/2-animation/2-bezier/demo.svg b/3-more/2-animation/2-bezier/demo.svg deleted file mode 100755 index 5ff89a6e..00000000 --- a/3-more/2-animation/2-bezier/demo.svg +++ /dev/null @@ -1 +0,0 @@ -1t:1 \ No newline at end of file diff --git a/3-more/2-animation/index.md b/3-more/2-animation/index.md deleted file mode 100644 index d940e7df..00000000 --- a/3-more/2-animation/index.md +++ /dev/null @@ -1,2 +0,0 @@ -# Анимация - diff --git a/3-more/2-animation/2-bezier/article.md b/3-more/3-animation/1-bezier/article.md similarity index 62% rename from 3-more/2-animation/2-bezier/article.md rename to 3-more/3-animation/1-bezier/article.md index 9696fd1b..5d7cf395 100644 --- a/3-more/2-animation/2-bezier/article.md +++ b/3-more/3-animation/1-bezier/article.md @@ -1,14 +1,13 @@ # Кривые Безье -Кривые Безье используются в компьютерной графике для рисования плавных изгибов, в [CSS-анимации](#css-animation) для описания процесса анимации и много где ещё. +Кривые Безье используются в компьютерной графике для рисования плавных изгибов, в CSS-анимации и много где ещё. -Тему эту стоит изучить, чтобы в дальнейшем с комфортом пользоваться этим замечательным инструментом. +Несмотря на "умное" название -- это очень простая штука. + +В принципе, можно создавать анимацию и без знания кривых Безье, но стоит один раз прочитать, что это такое, так как в векторной графике и продвинутых анимаций без них никак. Это образовательный минимум. + +Тему эту стоит изучить один раз, чтобы в дальнейшем с комфортом пользоваться этим замечательным инструментом. [cut] - ## Виды кривых Безье @@ -16,29 +15,24 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi Их может быть две, три, четыре или больше. Например: - - - - - - - - - - - -
По двум точкамПо трём точкамПо четырём точкам
+По двум точкам: + - + +По трём точкам: + - + +По четырём точкам: + -
+ Если вы посмотрите внимательно на эти кривые, то "на глазок" заметите:
    +
  1. **Точки не всегда на кривой.** Это совершенно нормально, как именно строится кривая мы рассмотрим чуть позже.
  2. **Степень кривой равна числу точек минус один**. -На рисунках выше, соответственно, получаются для двух точек -- линейная кривая (прямая), для трёх точек -- квадратическая кривая (парабола), для четырёх -- кубическая.
  3. +Для двух точек -- это линейная кривая (т.е. прямая), для трёх точек -- квадратическая кривая (парабола), для четырёх -- кубическая.
  4. **Кривая всегда находится внутри [выпуклой оболочки](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), образованной опорными точками:** @@ -47,13 +41,13 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi
-Основная ценность кривых Безье -- в том, что **кривую можно менять, двигая точки**. При этом **кривая меняется интуитивно понятным образом**. +Основная ценность кривых Безье -- в том, что, двигая точки, кривую можно менять, причём кривая при этом меняется интуитивно понятным образом. Попробуйте двигать точки мышью в примере ниже: [iframe src="demo.svg?nocpath=1&p=0,0,0.5,0,0.5,1,1,1" height=370] -Как можно заметить, **кривая натянута по касательным 1 -> 2 и 3 -> 4.** +**Как можно заметить, кривая натянута по касательным 1 -> 2 и 3 -> 4.** После небольшой практики становится понятно, как расположить точки, чтобы получить нужную форму. А, соединяя несколько кривых, можно получить практически что угодно. @@ -63,7 +57,9 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi ## Математика -У кривых Безье есть математическая формула. Как мы увидим далее, в ней нет особенной необходимости, но для полноты картины -- вот она. +У кривых Безье есть математическая формула. + +Как мы увидим далее, для пользования кривыми Безье знать её нет особенной необходимости, но для полноты картины -- вот она. **Координаты кривой описываются в зависимости от параметра `t⋲[0,1]`** @@ -88,28 +84,39 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi -Эти уравнения -- векторные, т.е. вместо Pi нужно подставить координаты i-й опорной точки (xi, yi). +Вместо Pi нужно подставить координаты i-й опорной точки (xi, yi). -Формула даёт возможность строить кривые, но не очень понятно, почему они именно такие, и как зависят от опорных точек. С этим нам поможет разобраться другой алгоритм. +Эти уравнения векторные, то есть на для каждой из координат: + + +Вместо 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) идентичен математическому определению кривой и наглядно показывает, как она строится. -Посмотрим его на примере трех точек (точки можно двигать). Нажатие на кнопку "edit" запустит демонстрацию. +Посмотрим его на примере трёх точек (точки можно двигать). Нажатие на кнопку "play" запустит демонстрацию. [iframe src="demo.svg?p=0,0,0.5,1,1,0&animate=1" height=370] -**Алгоритм построения "де Кастельжо":** +**Алгоритм построения кривой по "методу де Кастельжо":**
    - -
  1. Строятся отрезки между опорными точками 1-2-3. На рисунке выше они **чёрные**.
  2. +
  3. Рисуем опорные точки. В примере выше это `1`, `2`, `3`.
  4. +
  5. Строятся отрезки между опорными точками 1 -> 2 -> 3. На рисунке выше они **чёрные**.
  6. Параметр `t` пробегает значения от `0` до `1`. В примере выше использован шаг `0.05`, т.е. в цикле `0, 0.05, 0.1, 0.15, ... 0.95, 1`. -Для каждого значения `t`: +Значение `t` пробегает интервал от 0 до 1, для каждого `t`:
      -
    1. На каждом из этих отрезков берётся точка, находящаяся от начала на расстоянии от 0 до `t` пропорционально длине. То есть, при `t=0` -- точка будет в начале, при `t=0.25` -- на расстоянии в 25% от начала отрезка, при `t=0.5` -- 50%(на середине), при `t=1` -- в конце. Так как **чёрных** отрезков -- два, то и точек выходит две штуки.
    2. +
    3. На каждом из этих отрезков берётся точка, находящаяся от начала на расстоянии от 0 до `t` пропорционально длине. Так как чёрных отрезков -- два, то и точек выходит две штуки. + +То есть, при `t=0` -- точки будут в начале, при `t=0.25` -- на расстоянии в 25% от начала отрезка, при `t=0.5` -- 50%(на середине), при `t=1` -- в конце отрезка. +
    4. Эти точки соединяются. На рисунке ниже соединяющий их отрезок изображён синим. @@ -121,7 +128,7 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi
    5. -
    6. На получившемся отрезке берётся точка на расстоянии, соответствующем `t`. То есть, для `t=0.25` получаем точку в конце первой четверти отрезка, для `t=0.5` -- в середине отрезка. На рисунке выше эта точка отмечена красным. +
    7. На получившемся отрезке берётся точка на расстоянии, соответствующем `t`. То есть, для `t=0.25` (первый рисунок) получаем точку в конце первой четверти отрезка, для `t=0.5` (второй рисунок) -- в середине отрезка. На рисунках выше эта точка отмечена красным.
  7. @@ -138,14 +145,14 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi Алгоритм: -Нажмите на кнопку "edit" в примере выше, чтобы увидеть это в действии. +Нажмите на кнопку "play" в примере выше, чтобы увидеть это в действии. Ещё примеры кривых: @@ -165,12 +172,12 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi Аналогичным образом могут быть построены кривые Безье и более высокого порядка: по пяти точкам, шести и так далее. Но обычно используются 2-3 точки, а для сложных линий несколько кривых соединяются. Это гораздо проще с точки зрения поддержки и расчётов. -[smart header="Как провести кривую через нужные точки?"] -Этот вопрос не связан с кривыми Безье, но он иногда возникает в смежных задачах. +[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%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). +Как правило, в компьютерной графике для интерполяции используют кубические кривые, соединённых гладким образом. Вместе они выглядят как одна кривая. Это называется [интерполяция сплайнами](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). [/smart] ## Итого @@ -180,12 +187,16 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Basi
  8. Через процесс построения де Кастельжо.
-С их помощью можно описать почти любую линию, особенно если соединить несколько. +Их удобство в том, что: + Применение: \ No newline at end of file diff --git a/3-more/2-animation/2-bezier/bezier2.png b/3-more/3-animation/1-bezier/bezier2.png old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/2-bezier/bezier2.png rename to 3-more/3-animation/1-bezier/bezier2.png diff --git a/3-more/2-animation/2-bezier/bezier3-draw1.png b/3-more/3-animation/1-bezier/bezier3-draw1.png old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/2-bezier/bezier3-draw1.png rename to 3-more/3-animation/1-bezier/bezier3-draw1.png diff --git a/3-more/2-animation/2-bezier/bezier3-draw2.png b/3-more/3-animation/1-bezier/bezier3-draw2.png old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/2-bezier/bezier3-draw2.png rename to 3-more/3-animation/1-bezier/bezier3-draw2.png diff --git a/3-more/2-animation/2-bezier/bezier3-e.png b/3-more/3-animation/1-bezier/bezier3-e.png old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/2-bezier/bezier3-e.png rename to 3-more/3-animation/1-bezier/bezier3-e.png diff --git a/3-more/2-animation/2-bezier/bezier3.png b/3-more/3-animation/1-bezier/bezier3.png old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/2-bezier/bezier3.png rename to 3-more/3-animation/1-bezier/bezier3.png diff --git a/3-more/2-animation/2-bezier/bezier4-e.png b/3-more/3-animation/1-bezier/bezier4-e.png old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/2-bezier/bezier4-e.png rename to 3-more/3-animation/1-bezier/bezier4-e.png diff --git a/3-more/2-animation/2-bezier/bezier4.png b/3-more/3-animation/1-bezier/bezier4.png old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/2-bezier/bezier4.png rename to 3-more/3-animation/1-bezier/bezier4.png diff --git a/3-more/2-animation/2-bezier/car.jpg b/3-more/3-animation/1-bezier/car.jpg old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/2-bezier/car.jpg rename to 3-more/3-animation/1-bezier/car.jpg diff --git a/3-more/3-animation/1-bezier/demo.svg b/3-more/3-animation/1-bezier/demo.svg new file mode 100644 index 00000000..7dd51ad6 --- /dev/null +++ b/3-more/3-animation/1-bezier/demo.svg @@ -0,0 +1 @@ + 1 t:1 \ No newline at end of file diff --git a/3-more/2-animation/2-bezier/letter_m.png b/3-more/3-animation/1-bezier/letter_m.png old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/2-bezier/letter_m.png rename to 3-more/3-animation/1-bezier/letter_m.png diff --git a/3-more/3-animation/1-bezier/play.png b/3-more/3-animation/1-bezier/play.png new file mode 100644 index 0000000000000000000000000000000000000000..03131b1dc4a8b4e832c7e44603ecb2f234e51404 GIT binary patch literal 4702 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 literal 0 HcmV?d00001 diff --git a/3-more/2-animation/2-bezier/vase.png b/3-more/3-animation/1-bezier/vase.png old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/2-bezier/vase.png rename to 3-more/3-animation/1-bezier/vase.png diff --git a/3-more/2-animation/3-css-animation/1-animate-logo-css/solution.md b/3-more/3-animation/2-css-transitions/1-animate-logo-css/solution.md similarity index 100% rename from 3-more/2-animation/3-css-animation/1-animate-logo-css/solution.md rename to 3-more/3-animation/2-css-transitions/1-animate-logo-css/solution.md diff --git a/3-more/2-animation/3-css-animation/1-animate-logo-css/solution.view/index.html b/3-more/3-animation/2-css-transitions/1-animate-logo-css/solution.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/3-css-animation/1-animate-logo-css/solution.view/index.html rename to 3-more/3-animation/2-css-transitions/1-animate-logo-css/solution.view/index.html diff --git a/3-more/2-animation/1-js-animation/1-carousel-animated/solution.view/animate.js b/3-more/3-animation/2-css-transitions/1-animate-logo-css/source.view/animate.js old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/1-carousel-animated/solution.view/animate.js rename to 3-more/3-animation/2-css-transitions/1-animate-logo-css/source.view/animate.js diff --git a/3-more/2-animation/1-js-animation/2-animate-logo/source.view/index.html b/3-more/3-animation/2-css-transitions/1-animate-logo-css/source.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/2-animate-logo/source.view/index.html rename to 3-more/3-animation/2-css-transitions/1-animate-logo-css/source.view/index.html diff --git a/3-more/2-animation/3-css-animation/1-animate-logo-css/task.md b/3-more/3-animation/2-css-transitions/1-animate-logo-css/task.md similarity index 100% rename from 3-more/2-animation/3-css-animation/1-animate-logo-css/task.md rename to 3-more/3-animation/2-css-transitions/1-animate-logo-css/task.md diff --git a/3-more/2-animation/3-css-animation/article.md b/3-more/3-animation/2-css-transitions/article.md similarity index 78% rename from 3-more/2-animation/3-css-animation/article.md rename to 3-more/3-animation/2-css-transitions/article.md index 13dde71f..330b14ec 100644 --- a/3-more/2-animation/3-css-animation/article.md +++ b/3-more/3-animation/2-css-transitions/article.md @@ -1,11 +1,10 @@ -# CSS-анимация +# CSS-transitions Все современные браузеры, кроме IE9- поддерживают CSS transitions, которые позволяют реализовать анимацию средствами CSS, без привлечения JavaScript. -Большинство примеров из этой статьи не будут работать в IE9-. [cut] -## Анимация свойства [#css-animation] +## Анимация свойства [#css-transition] Идея проста. Вы указываете, что некоторое свойство будет анимироваться при помощи специальных CSS-правил. Далее, при изменении этого свойства, браузер сам обработает анимацию. @@ -18,7 +17,7 @@ } ``` -Любое изменение фонового цвета будет анимироваться в течение 2-х секунд. +Теперь любое изменение фонового цвета будет анимироваться в течение 2-х секунд. У свойства `"transition"` есть и короткая запись: @@ -28,46 +27,7 @@ } ``` -Так как [стандарт CSS Transitions](http://www.w3.org/TR/css3-transitions/) находится в стадии разработки, то `transition` нужно снабжать браузерными префиксами. - -### Пример -Этот пример работает во всех современных браузерах, не работает в IE9-. - -```html - -
- Кликни меня -
-``` - - -
- Кликни меня -
- -CSS-анимации особенно рекомендуются на мобильных устройствах. Они отрисовываются плавнее, чем JavaScript, и меньше нагружают процессор, так как используют графическую акселерацию. - - -## Полный синтаксис CSS +## Полный синтаксис Свойства для CSS-анимаций:
@@ -76,41 +36,27 @@ CSS-анимации особенно рекомендуются на мобил
`transition-duration`
Продолжительность анимации. Если указано одно значение -- оно применится ко всем свойствам, можно указать несколько значений для разных `transition-property`.
`transition-timing-function`
-
[Кривая Безье](/bezier) по 4-м точкам, используемая в качестве временной функциии.
+
Кривая Безье по 4-м точкам, используемая в качестве временной функциии. Их мы изучим [чуть позже](/bezier)
`transition-delay`
Указывает задержку от изменения свойства до начала CSS-анимации.
Свойство **`transition`** может содержать их все, в порядке: `property duration timing-function delay, ...`. -### Пример +## Пример Анимируем одновременно цвет и размер шрифта: ```html + ``` - - - ## Временнáя функция В качестве временной функции можно выбрать любую [кривую Безье](/bezier), удовлетворяющую условиям: diff --git a/3-more/2-animation/3-css-animation/boat.view/index.html b/3-more/3-animation/2-css-transitions/boat.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/3-css-animation/boat.view/index.html rename to 3-more/3-animation/2-css-transitions/boat.view/index.html diff --git a/3-more/2-animation/3-css-animation/ease-in-out.png b/3-more/3-animation/2-css-transitions/ease-in-out.png old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/3-css-animation/ease-in-out.png rename to 3-more/3-animation/2-css-transitions/ease-in-out.png diff --git a/3-more/2-animation/3-css-animation/ease-in.png b/3-more/3-animation/2-css-transitions/ease-in.png old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/3-css-animation/ease-in.png rename to 3-more/3-animation/2-css-transitions/ease-in.png diff --git a/3-more/2-animation/3-css-animation/ease-out.png b/3-more/3-animation/2-css-transitions/ease-out.png old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/3-css-animation/ease-out.png rename to 3-more/3-animation/2-css-transitions/ease-out.png diff --git a/3-more/2-animation/3-css-animation/ease.png b/3-more/3-animation/2-css-transitions/ease.png old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/3-css-animation/ease.png rename to 3-more/3-animation/2-css-transitions/ease.png diff --git a/3-more/2-animation/3-css-animation/train-curve.png b/3-more/3-animation/2-css-transitions/train-curve.png old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/3-css-animation/train-curve.png rename to 3-more/3-animation/2-css-transitions/train-curve.png diff --git a/3-more/2-animation/1-js-animation/1-carousel-animated/solution.md b/3-more/3-animation/3-js-animation/1-carousel-animated/solution.md similarity index 100% rename from 3-more/2-animation/1-js-animation/1-carousel-animated/solution.md rename to 3-more/3-animation/3-js-animation/1-carousel-animated/solution.md diff --git a/3-more/2-animation/1-js-animation/2-animate-logo/solution.view/animate.js b/3-more/3-animation/3-js-animation/1-carousel-animated/solution.view/animate.js old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/2-animate-logo/solution.view/animate.js rename to 3-more/3-animation/3-js-animation/1-carousel-animated/solution.view/animate.js diff --git a/3-more/2-animation/1-js-animation/1-carousel-animated/solution.view/index.html b/3-more/3-animation/3-js-animation/1-carousel-animated/solution.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/1-carousel-animated/solution.view/index.html rename to 3-more/3-animation/3-js-animation/1-carousel-animated/solution.view/index.html diff --git a/3-more/2-animation/1-js-animation/1-carousel-animated/solution.view/style.css b/3-more/3-animation/3-js-animation/1-carousel-animated/solution.view/style.css old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/1-carousel-animated/solution.view/style.css rename to 3-more/3-animation/3-js-animation/1-carousel-animated/solution.view/style.css diff --git a/3-more/2-animation/1-js-animation/1-carousel-animated/task.md b/3-more/3-animation/3-js-animation/1-carousel-animated/task.md similarity index 100% rename from 3-more/2-animation/1-js-animation/1-carousel-animated/task.md rename to 3-more/3-animation/3-js-animation/1-carousel-animated/task.md diff --git a/3-more/2-animation/1-js-animation/2-animate-logo/solution.md b/3-more/3-animation/3-js-animation/2-animate-logo/solution.md similarity index 100% rename from 3-more/2-animation/1-js-animation/2-animate-logo/solution.md rename to 3-more/3-animation/3-js-animation/2-animate-logo/solution.md diff --git a/3-more/2-animation/1-js-animation/2-animate-logo/source.view/animate.js b/3-more/3-animation/3-js-animation/2-animate-logo/solution.view/animate.js old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/2-animate-logo/source.view/animate.js rename to 3-more/3-animation/3-js-animation/2-animate-logo/solution.view/animate.js diff --git a/3-more/2-animation/1-js-animation/2-animate-logo/solution.view/index.html b/3-more/3-animation/3-js-animation/2-animate-logo/solution.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/2-animate-logo/solution.view/index.html rename to 3-more/3-animation/3-js-animation/2-animate-logo/solution.view/index.html diff --git a/3-more/2-animation/3-css-animation/1-animate-logo-css/source.view/animate.js b/3-more/3-animation/3-js-animation/2-animate-logo/source.view/animate.js old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/3-css-animation/1-animate-logo-css/source.view/animate.js rename to 3-more/3-animation/3-js-animation/2-animate-logo/source.view/animate.js diff --git a/3-more/2-animation/3-css-animation/1-animate-logo-css/source.view/index.html b/3-more/3-animation/3-js-animation/2-animate-logo/source.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/3-css-animation/1-animate-logo-css/source.view/index.html rename to 3-more/3-animation/3-js-animation/2-animate-logo/source.view/index.html diff --git a/3-more/2-animation/1-js-animation/2-animate-logo/task.md b/3-more/3-animation/3-js-animation/2-animate-logo/task.md similarity index 100% rename from 3-more/2-animation/1-js-animation/2-animate-logo/task.md rename to 3-more/3-animation/3-js-animation/2-animate-logo/task.md diff --git a/3-more/2-animation/1-js-animation/3-animate-ball/solution.md b/3-more/3-animation/3-js-animation/3-animate-ball/solution.md similarity index 100% rename from 3-more/2-animation/1-js-animation/3-animate-ball/solution.md rename to 3-more/3-animation/3-js-animation/3-animate-ball/solution.md diff --git a/3-more/2-animation/1-js-animation/3-animate-ball/solution.view/animate.js b/3-more/3-animation/3-js-animation/3-animate-ball/solution.view/animate.js old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/3-animate-ball/solution.view/animate.js rename to 3-more/3-animation/3-js-animation/3-animate-ball/solution.view/animate.js diff --git a/3-more/2-animation/1-js-animation/3-animate-ball/solution.view/index.html b/3-more/3-animation/3-js-animation/3-animate-ball/solution.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/3-animate-ball/solution.view/index.html rename to 3-more/3-animation/3-js-animation/3-animate-ball/solution.view/index.html diff --git a/3-more/2-animation/1-js-animation/3-animate-ball/source.view/animate.js b/3-more/3-animation/3-js-animation/3-animate-ball/source.view/animate.js old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/3-animate-ball/source.view/animate.js rename to 3-more/3-animation/3-js-animation/3-animate-ball/source.view/animate.js diff --git a/3-more/2-animation/1-js-animation/3-animate-ball/source.view/index.html b/3-more/3-animation/3-js-animation/3-animate-ball/source.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/3-animate-ball/source.view/index.html rename to 3-more/3-animation/3-js-animation/3-animate-ball/source.view/index.html diff --git a/3-more/2-animation/1-js-animation/3-animate-ball/task.md b/3-more/3-animation/3-js-animation/3-animate-ball/task.md similarity index 100% rename from 3-more/2-animation/1-js-animation/3-animate-ball/task.md rename to 3-more/3-animation/3-js-animation/3-animate-ball/task.md diff --git a/3-more/2-animation/1-js-animation/4-animate-ball-hops/solution.md b/3-more/3-animation/3-js-animation/4-animate-ball-hops/solution.md similarity index 100% rename from 3-more/2-animation/1-js-animation/4-animate-ball-hops/solution.md rename to 3-more/3-animation/3-js-animation/4-animate-ball-hops/solution.md diff --git a/3-more/2-animation/1-js-animation/4-animate-ball-hops/solution.view/animate.js b/3-more/3-animation/3-js-animation/4-animate-ball-hops/solution.view/animate.js old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/4-animate-ball-hops/solution.view/animate.js rename to 3-more/3-animation/3-js-animation/4-animate-ball-hops/solution.view/animate.js diff --git a/3-more/2-animation/1-js-animation/4-animate-ball-hops/solution.view/index.html b/3-more/3-animation/3-js-animation/4-animate-ball-hops/solution.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/4-animate-ball-hops/solution.view/index.html rename to 3-more/3-animation/3-js-animation/4-animate-ball-hops/solution.view/index.html diff --git a/3-more/2-animation/1-js-animation/4-animate-ball-hops/source.view/animate.js b/3-more/3-animation/3-js-animation/4-animate-ball-hops/source.view/animate.js old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/4-animate-ball-hops/source.view/animate.js rename to 3-more/3-animation/3-js-animation/4-animate-ball-hops/source.view/animate.js diff --git a/3-more/2-animation/1-js-animation/4-animate-ball-hops/source.view/index.html b/3-more/3-animation/3-js-animation/4-animate-ball-hops/source.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/4-animate-ball-hops/source.view/index.html rename to 3-more/3-animation/3-js-animation/4-animate-ball-hops/source.view/index.html diff --git a/3-more/2-animation/1-js-animation/4-animate-ball-hops/task.md b/3-more/3-animation/3-js-animation/4-animate-ball-hops/task.md similarity index 100% rename from 3-more/2-animation/1-js-animation/4-animate-ball-hops/task.md rename to 3-more/3-animation/3-js-animation/4-animate-ball-hops/task.md diff --git a/3-more/2-animation/1-js-animation/article.md b/3-more/3-animation/3-js-animation/article.md similarity index 100% rename from 3-more/2-animation/1-js-animation/article.md rename to 3-more/3-animation/3-js-animation/article.md diff --git a/3-more/2-animation/1-js-animation/back.svg b/3-more/3-animation/3-js-animation/back.svg similarity index 100% rename from 3-more/2-animation/1-js-animation/back.svg rename to 3-more/3-animation/3-js-animation/back.svg diff --git a/3-more/2-animation/1-js-animation/bounce-inout.svg b/3-more/3-animation/3-js-animation/bounce-inout.svg similarity index 100% rename from 3-more/2-animation/1-js-animation/bounce-inout.svg rename to 3-more/3-animation/3-js-animation/bounce-inout.svg diff --git a/3-more/2-animation/1-js-animation/circ-ease.svg b/3-more/3-animation/3-js-animation/circ-ease.svg similarity index 100% rename from 3-more/2-animation/1-js-animation/circ-ease.svg rename to 3-more/3-animation/3-js-animation/circ-ease.svg diff --git a/3-more/2-animation/1-js-animation/circ.svg b/3-more/3-animation/3-js-animation/circ.svg similarity index 100% rename from 3-more/2-animation/1-js-animation/circ.svg rename to 3-more/3-animation/3-js-animation/circ.svg diff --git a/3-more/2-animation/1-js-animation/elastic.svg b/3-more/3-animation/3-js-animation/elastic.svg similarity index 100% rename from 3-more/2-animation/1-js-animation/elastic.svg rename to 3-more/3-animation/3-js-animation/elastic.svg diff --git a/3-more/2-animation/1-js-animation/linear.svg b/3-more/3-animation/3-js-animation/linear.svg similarity index 100% rename from 3-more/2-animation/1-js-animation/linear.svg rename to 3-more/3-animation/3-js-animation/linear.svg diff --git a/3-more/2-animation/1-js-animation/move.view/index.html b/3-more/3-animation/3-js-animation/move.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/move.view/index.html rename to 3-more/3-animation/3-js-animation/move.view/index.html diff --git a/3-more/2-animation/1-js-animation/move100.view/index.html b/3-more/3-animation/3-js-animation/move100.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/move100.view/index.html rename to 3-more/3-animation/3-js-animation/move100.view/index.html diff --git a/3-more/2-animation/1-js-animation/quad.svg b/3-more/3-animation/3-js-animation/quad.svg similarity index 100% rename from 3-more/2-animation/1-js-animation/quad.svg rename to 3-more/3-animation/3-js-animation/quad.svg diff --git a/3-more/2-animation/1-js-animation/quint.svg b/3-more/3-animation/3-js-animation/quint.svg similarity index 100% rename from 3-more/2-animation/1-js-animation/quint.svg rename to 3-more/3-animation/3-js-animation/quint.svg diff --git a/3-more/2-animation/1-js-animation/width.view/index.html b/3-more/3-animation/3-js-animation/width.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 3-more/2-animation/1-js-animation/width.view/index.html rename to 3-more/3-animation/3-js-animation/width.view/index.html diff --git a/3-more/3-animation/index.md b/3-more/3-animation/index.md new file mode 100644 index 00000000..51699284 --- /dev/null +++ b/3-more/3-animation/index.md @@ -0,0 +1,3 @@ +# Анимация [todo] + +CSS анимации. Контроль над ними из JavaScript. Анимации на чистом JavaScript. \ No newline at end of file diff --git a/3-more/4-optimize/1-memory-leaks/article.md b/3-more/4-optimize/1-memory-leaks/article.md index 7e511a09..0cc9d101 100644 --- a/3-more/4-optimize/1-memory-leaks/article.md +++ b/3-more/4-optimize/1-memory-leaks/article.md @@ -13,53 +13,15 @@ ## Коллекция утечек в IE -### Утечка DOM ↔ JS в IE7- +### Утечка DOM ↔ JS в IE8- IE до версии 8 не умел очищать циклические ссылки, появляющиеся между DOM-объектами и объектами JavaScript. В результате и DOM и JS оставались в памяти навсегда. -[warn header="Пропустите эту секцию, если IE8- не нужен"] -Проблема была особенно серьезна в IE6 до SP3 (или до обновления июня 2007 года), там память не освобождалась даже при переходе на другую страницу. +В браузере IE8 была проведена серьёзная работа над ошибками, но утечка в IE8- появляется, если круговая ссылка возникает "через объект". -Сейчас она существует в IE6, 7, а также, в облегчённом варианте, в IE8 (см. далее). Если вы не поддерживаете IE8-, то можете пропустить эту секцию. -[/warn] +Чтобы было понятнее, о чём речь, посмотрите на следующий код. Он вызывает утечку памяти в IE8-: -Функция `setHandler` в примере ниже ведёт к утечке памяти в IE6,7: - -```js -function setHandler() { - var elem = document.getElementById('id'); - elem.onclick = function() { - /* может быть пустая функция, не важно */ - }; -} ``` - -Элемент `elem` здесь ссылается на JavaScript-функцию через ссылку `onclick` напрямую, через свойство, а функция ссылается на `elem` через замыкание. - - - -Здесь вместо DOM-элемента в IE может быть `XMLHttpRequest`, `ActiveX`, любой другой COM-объект. Круговая ссылка гарантирует утечку. - - -**Обойти утечки памяти в IE можно, разорвав циклические ссылки.** - -Например, можно удалить ссылку на `elem` из замыкания, присвоив `elem = null`. Таким образом обработчик больше не ссылается на DOM-элемент. Циклическая ссылка разорвана: - - - - -Больше информации об этой утечке вы можете почерпнуть из статей: Understanding and Solving Internet Explorer Leak Patterns и Circular Memory Leak Mitigation. - - -### Утечка DOM ↔ JS, вариант для IE8- - -В браузере IE8 была проведена серьёзная работа над ошибками, и пример, описанный выше, больше не приводит к утечке. - -**Но ситуация исправлена не до конца. Утечка в IE8- появляется, если круговая ссылка возникает "через объект".** - -Чтобы было понятнее, о чём речь, посмотрите на следующий код. Он вызывает утечку памяти: - -```js function leak() { // Создаём новый DIV, добавляем к BODY var elem = document.createElement('div'); @@ -80,11 +42,12 @@ function leak() { } ``` -Открыть в новом окне (в IE) +Полный пример (только для IE8-, а также IE9 в режиме совместимости с IE8): -Этот пример, течёт в IE6,7,8, а также в IE9 в режиме совместимости с IE8. Проблема -- в круговой ссылке `elem.__expando__elem = elem`. +[codetabs src="leak-ie8"] -**Утечка может возникать и неявным образом, через замыкание:** + +Круговая ссылка и, как следствие, утечка может возникать и неявным образом, через замыкание: ```js function leak() { @@ -103,32 +66,17 @@ function leak() { } ``` -Открыть в новом окне (в IE) +Полный пример (IE8-, IE9 в режиме совместимости с IE8): -**Без метода `method` здесь утечки не возникнет.** +[codetabs src="leak-ie8-2"] + +Без привязки метода `method` к элементу здесь утечки не возникнет. Бывает ли такая ситуация в реальной жизни? Или это -- целиком синтетический пример, для заумных программистов? -Да, конечно бывает. Например, при разработке графических компонент. - -Во-первых, сам объект компонента хранит ссылку на его DOM-элемент, чтобы работать с ним. Например: - -```js -function Menu(elem) { - elem.onclick = function() { - // ссылка на elem осталась в замыкании - }; -} - -var menu = new Menu(elem); -``` - -То есть, компонент всегда знает свой элемент. - -Но бывают ситуации, когда нужно пойти в обратном направлении, а именно -- по элементу определить, какой на нём компонент. Например, при делегировании, чтобы передать обработку события на элементе соответствующему компоненту. Или при Drag'n'Drop, чтобы получить компонент, соответствующий элементу, на который произведён перенос. - -Сама задача не является чем-то из ряда вон выходящим. Вполне естественно, что JS-компонент привязан к элементу, а элемент знает о компоненте на нём. Но в IE8- прямая привязка ведёт к утечке памяти! +Да, конечно бывает. Например, при разработке графических компонент -- бывает удобно присвоить DOM-элементу ссылку на JavaScript-объект, который представляет собой компонент. Это упрощает делегирование и, в общем-то, логично, что DOM-элемент знает о компоненте на себе. Но в IE8- прямая привязка ведёт к утечке памяти! +Примерно так: ```js function Menu(elem) { elem.onclick = function() {}; @@ -136,12 +84,13 @@ function Menu(elem) { var menu = new Menu(elem); // Menu содержит ссылку на elem *!* -elem.menu = menu; // вот такая привязка или что-то подобное ведёт к утечке +elem.menu = menu; // такая привязка или что-то подобное ведёт к утечке в IE8 +*/!* ``` -Открыть в новом окне (в IE) +Полный пример (IE8-, IE9 в режиме совместимости с IE8): -Такая привязка удобна, т.к. мы по DOM-элементу можем получить JS-компонент, который к нему привязан. Но, как видим, ведёт к утечке в IE8-. +[codetabs src="leak-ie8-widget"] ### Утечка IE8 при обращении к коллекциям таблицы @@ -168,7 +117,9 @@ function leak() { } ``` -Открыть в новом окне (в IE) +Полный пример (IE8): + +[codetabs src="leak-ie8-table"] Особенности:
    @@ -217,10 +168,12 @@ function leak() { Когда запускается асинхронный запрос `xhr`, браузер создаёт специальную внутреннюю ссылку (internal reference) на этот объект. находится в процессе коммуникации. Именно поэтому объект `xhr` будет жив после окончания работы функции. -**Когда запрос завершен, браузер удаляет внутреннюю ссылку, `xhr` становится недостижимым и память очищается... Везде, кроме IE8-.** +Когда запрос завершен, браузер удаляет внутреннюю ссылку, `xhr` становится недостижимым и память очищается... Везде, кроме IE8-. -Открыть в новом окне (в IE8-) (откройте страницу и пусть поработает минут 20 - съест всю память, включая виртуальную). +Полный пример (IE8): + +[codetabs src="leak-ie8-xhr"] Чтобы это исправить, нам нужно разорвать круговую ссылку `XMLHttpRequest ↔ JS`. Например, можно удалить `xhr` из замыкания: @@ -248,9 +201,7 @@ function leak() { -Теперь циклической ссылки нет -- мы устранили утечку. - -Посмотреть исправленный пример для IE в отдельном окне. +Теперь циклической ссылки нет -- и не будет утечки. ## Объемы утечек памяти @@ -273,13 +224,11 @@ function f() { } ``` -**Пока функция `inner` остается в памяти, `LexicalEnvironment` с переменной большого объема внутри висит в памяти.** +Пока функция `inner` остается в памяти, `LexicalEnvironment` с переменной большого объема внутри висит в памяти. Висит до тех пор, пока функция `inner` жива. -**Как правило, JavaScript не знает, какие из переменных функции `inner` будут использованы, поэтому оставляет их все.** - -Исключение -- виртуальная машина V8 (Chrome, Opera, Node.JS), она обычно видит, что переменная не используется во внутренних функциях, и очистит память. +Как правило, JavaScript не знает, какие из переменных функции `inner` будут использованы, поэтому оставляет их все. Исключение -- виртуальная машина V8 (Chrome, Opera, Node.JS), она часто (не всегда) видит, что переменная не используется во внутренних функциях, и очистит память. В других же интерпретаторах, даже если код спроектирован так, что никакой утечки нет, по вполне разумной причине может создаваться множество функций, а память будет расти потому, что функция тянет за собой своё замыкание. @@ -303,113 +252,6 @@ function f() { } ``` -## jQuery: утечки и борьба с утечками - -[warn header="Изменения в jQuery 2"] -В jQuery 2 объект с данными элемента, о котором идёт речь далее, более недоступен извне. Он стал локальной переменной внутри jQuery с именем `data_priv`, явный доступ к внутренним данным более невозможен (или deprecated). - -Но в остальном всё работает точно так, как описано, и с теми же последствиями. -[/warn] - -**В jQuery для борьбы с утечками памяти в IE6-7 используется $.data API. Однако, это может стать причиной новых(!) утечек, характерных для jQuery.** - -Основной принцип `$.data` — это для любого JavaScript объекта сохранить/получить значение для элемента с помощью jQuery вызова: - -```js -//+ run -$(document.body).data('prop', { anything: "любой объект" }) // set -alert( $(document.body).data('prop') ) // get -``` - -jQuery `elem.data(prop, val)` делает следующее: -
      -
    1. Элемент получает уникальный идентификатор, если у него такого еще нет: - -```js -elem[ jQuery.expando ] = id = ++jQuery.uuid; // средствами jQuery -``` - -`jQuery.expando` -- это случайная строка, сгенерированная jQuery один раз при входе на страницу. Уникальное свойство, чтобы ничего важного не перезаписать.
    2. -
    3. ...А сами данные сохраняются в специальном объекте `jQuery.cache`: - -```js -jQuery.cache[id]['prop'] = { anything: "любой объект" }; -``` - -
    4. -
    - -Когда данные считываются из элемента: - -
      -
    1. Уникальный идентификатор элемента извлекается из `id = elem[ jQuery.expando]`. -
    2. Данные считываются из `jQuery.cache[id]`.
    3. -
    - -Смысл этого API в том, что DOM-элемент никогда не ссылается на JavaScript объект напрямую. Задействуется идентификатор, а сами данные хранятся в `jQuery.cache`. Утечек в IE не будет. - -К тому же все данные известны библиотеке, так что можно клонировать с ними и т.п. - -**Как побочный эффект -- возникает утечка памяти, если элемент удален из DOM без дополнительной очистки.** - -### Примеры утечек в jQuery - -Следующий код создает jQuery-утечку во всех браузерах: - -```js -$('
    ') - .html(new Array(1000).join('text')) // div с текстом, возможна AJAX-загрузка - .click(function() { }) - .appendTo('#data') - -document.getElementById('data').innerHTML = ''; // (*) -``` - -Показать в отдельном окне - -Утечка происходит потому, что обработчик события в jQuery хранится в данных элемента. В строке `(*)` элемент удален очисткой родительского `innerHTML`, но в `jQuery.cache` данные остались. - -Более того, система обработки событий в jQuery устроена так, что вместе с обработчиком в данных хранится и ссылка на элемент, так что в итоге оба -- и обработчик и элемент -- остаются в памяти вместе со всем замыканием! - -**Ещё более простой пример утечки:** - -Этот код создает утечку: - -```js -function go() { - $('
    ') - .html(new Array(1000).join('text')) - .click(function() { }) -} -``` - -Показать в отдельном окне - -Причина здесь в том, что элемент `
    ` создан, но нигде не размещен :). После выполнения функции ссылка на него теряется. Но обработчик события `click` уже сохранил данные в `jQuery.cache`, которые застревают там навсегда. - -### Используем jQuery без утечек - -Чтобы избежать утечек, описанных выше, для удаления элементов используйте функции jQuery API, а не чистый JavaScript. - -Методы remove(), empty() и html() проверяют дочерние элементы на наличие данных и очищают их. Это несколько замедляет процедуру удаления, но зато освобождается память. - - -**К счастью обнаружить такие утечки легко. Проверьте размер `$.cache.`** Если он большой и растет, то изучите кэш, посмотрите, какие записи остаются и почему. - -### Улучшение производительности jQuery - -У способа борьбы с утечками IE, применённого в jQuery, есть побочный эффект. - -**Функции, удаляющие элементы, бегают по всему дереву DOM и очищают подэлементы.** - -Представьте себе, что вы получили с сервера большую таблицу (в виде текста), вставили её в документ и хотите обновить. Вызов `$('table').remove()` будет бегать по всем ячейкам и искать в них данные. Но мы-то знаем, что обработчики назначены через делегирование, и тратить на это время ни к чему! - -Чтобы "грязно" удалить элемент, без чистки, можно воспользоваться методом detach(). Его официальное назначение -- в том, чтобы убрать элемент из DOM, но сохранить возможность для вставки (и, соответственно, оставить на нём все данные). А неофициальное -- быстро убрать элемент из DOM. Если на нём нет данных и обработчиков, то всё хорошо. - -В принципе, если хочется всё сделать чисто, но быстро -- никто не мешает сделать `elem.detach()` и поместить вызов `elem.remove()` в `setTimeout`. В результате очистка будет происходить ассинхронно и незаметно. - -Итак, будем надеяться, что эта тема для вас теперь прозрачна и ясна и в следующих разделах мы не будем больше говорить об утечках в jQuery. - ## Поиск и устранение утечек памяти ### Проверка на утечки @@ -472,9 +314,4 @@ firefox --profilemanager Утечки памяти штука довольно сложная. В борьбе с ними вам определенно понадобится одна вещь: *Удача!* -
    -
    - -

    Перевести с английского варианта
    учебника помог Марат Шагиев

    - diff --git a/3-more/4-optimize/1-memory-leaks/leak-ie8-2.view/index.html b/3-more/4-optimize/1-memory-leaks/leak-ie8-2.view/index.html new file mode 100644 index 00000000..485bbee7 --- /dev/null +++ b/3-more/4-optimize/1-memory-leaks/leak-ie8-2.view/index.html @@ -0,0 +1,32 @@ + + + + + + + + + + + +

    Нажимайте на кнопку и наблюдайте, как увеличивается количество занимаемой браузером памяти.

    + + + + \ No newline at end of file diff --git a/3-more/4-optimize/1-memory-leaks/leak-ie8-table.view/index.html b/3-more/4-optimize/1-memory-leaks/leak-ie8-table.view/index.html new file mode 100644 index 00000000..b31ed103 --- /dev/null +++ b/3-more/4-optimize/1-memory-leaks/leak-ie8-table.view/index.html @@ -0,0 +1,33 @@ + + + + + + + +

    Нажимайте на кнопку и наблюдайте, как увеличивается количество занимаемой браузером памяти.

    + + + + + \ No newline at end of file diff --git a/3-more/4-optimize/1-memory-leaks/leak-ie8-widget.view/index.html b/3-more/4-optimize/1-memory-leaks/leak-ie8-widget.view/index.html new file mode 100644 index 00000000..6a071791 --- /dev/null +++ b/3-more/4-optimize/1-memory-leaks/leak-ie8-widget.view/index.html @@ -0,0 +1,38 @@ + + + + + + + + + + + +

    Нажимайте на кнопку и наблюдайте, как увеличивается количество занимаемой браузером памяти.

    + + + + + \ No newline at end of file diff --git a/3-more/4-optimize/1-memory-leaks/leak-ie8-xhr.view/index.html b/3-more/4-optimize/1-memory-leaks/leak-ie8-xhr.view/index.html new file mode 100644 index 00000000..71dae9f6 --- /dev/null +++ b/3-more/4-optimize/1-memory-leaks/leak-ie8-xhr.view/index.html @@ -0,0 +1,35 @@ + + + + + + + +

    Страница создаёт объект XMLHttpRequest каждые 50мс.

    + +

    Смотрите на память, она течёт в IE<9.

    + + + +
    Количество запросов: 0
    + + + \ No newline at end of file diff --git a/3-more/4-optimize/1-memory-leaks/leak-ie8.view/index.html b/3-more/4-optimize/1-memory-leaks/leak-ie8.view/index.html new file mode 100644 index 00000000..f0b88ce4 --- /dev/null +++ b/3-more/4-optimize/1-memory-leaks/leak-ie8.view/index.html @@ -0,0 +1,36 @@ + + + + + + + + + + + +

    Нажимайте на кнопку и наблюдайте, как увеличивается количество занимаемой браузером памяти.

    + + + + + \ No newline at end of file diff --git a/3-more/4-optimize/2-memory-leaks-jquery/article.md b/3-more/4-optimize/2-memory-leaks-jquery/article.md new file mode 100644 index 00000000..feb0bcb6 --- /dev/null +++ b/3-more/4-optimize/2-memory-leaks-jquery/article.md @@ -0,0 +1,125 @@ + +# Утечки памяти при использовании jQuery + +В jQuery для хранения обработчиков событий и других вспомогательных данных, связанных с DOM-элементами, используется внутренний объект, который в jQuery 1 доступен через $.data. + +В jQuery 2 доступ к нему закрыт через замыкание, он стал локальной переменной внутри jQuery с именем `data_priv`, но в остальном всё работает точно так, как описано, и с теми же последствиями. + +## $.data + +Встроенная функция `$.data` позволяет хранить привязывать произвольные значения к DOM-узлам. + +Например: + +```js +// присвоить +$(document).data('prop', { anything: "любой объект" }) + +// прочитать +alert( $(document).data('prop').anything ) // любой объект +``` + +Реализована она хитрым образом. Данные не хранятся в самом элементе, а во внутреннем объекте jQuery. + +jQuery-вызов `elem.data(prop, val)` делает следующее: + +
      +
    1. Элемент получает уникальный идентификатор, если у него такого еще нет: + +```js +elem[ jQuery.expando ] = id = ++jQuery.uuid; // средствами jQuery +``` + +`jQuery.expando` -- это случайная строка, сгенерированная jQuery один раз при входе на страницу. Уникальное свойство, чтобы ничего важного не перезаписать.
    2. +
    3. ...А сами данные сохраняются в специальном объекте `jQuery.cache`: + +```js +jQuery.cache[id]['prop'] = { anything: "любой объект" }; +``` + +
    4. +
    + +Когда данные считываются из элемента: + +
      +
    1. Уникальный идентификатор элемента извлекается из `id = elem[ jQuery.expando]`. +
    2. Данные считываются из `jQuery.cache[id]`.
    3. +
    + +Смысл этого API в том, что DOM-элемент никогда не ссылается на JavaScript объект напрямую. Задействуется идентификатор, а сами данные хранятся в `jQuery.cache`. Утечек в IE не будет. + +К тому же все данные известны библиотеке, так что можно клонировать с ними и т.п. + +Как побочный эффект -- возникает утечка памяти, если элемент удален из DOM без дополнительной очистки. + +## Примеры утечек в jQuery + +Следующий код создает jQuery-утечку во всех браузерах: + +```js +$('
    ') + .html(new Array(1000).join('text')) // div с текстом, возможна AJAX-загрузка + .click(function() { }) + .appendTo('#data') + +document.getElementById('data').innerHTML = ''; // (*) +``` + +Полный пример: + +[codetabs src="jquery-leak"] + +Утечка происходит потому, что обработчик события в jQuery хранится в данных элемента. В строке `(*)` элемент удален очисткой родительского `innerHTML`, но в `jQuery.cache` данные остались. + +Более того, система обработки событий в jQuery устроена так, что вместе с обработчиком в данных хранится и ссылка на элемент, так что в итоге оба -- и обработчик и элемент -- остаются в памяти вместе со всем замыканием! + +Ещё более простой пример утечки: + +Этот код также создает утечку: + +```js +function go() { + $('
    ') + .click(function() { }) +} +``` + +...То есть, мы создаём элемент, вешаем на него обработчик... И всё. + +Такой код ведёт к утечке памяти как раз потому, что элемент `
    ` создан, но нигде не размещен :). После выполнения функции ссылка на него теряется. Но обработчик события `click` уже сохранил данные в `jQuery.cache`, которые застревают там навсегда. + +## Используем jQuery без утечек + +Чтобы избежать утечек, описанных выше, для удаления элементов используйте функции jQuery API, а не чистый JavaScript. + +Методы remove(), empty() и html() проверяют дочерние элементы на наличие данных и очищают их. Это несколько замедляет процедуру удаления, но зато освобождается память. + +К счастью обнаружить такие утечки легко. Проверьте размер `$.cache`. Если он большой и растет, то изучите кэш, посмотрите, какие записи остаются и почему. + +## Улучшение производительности jQuery + +У способа организации внутренних данных, применённого в jQuery, есть важный побочный эффект. + +Функции, удаляющие элементы, также должны удалить и связанные с ними внутренние данные. Для этого нужно для каждого удаляемого элемента проверить -- а нет ли чего во внутреннем хранилище? И, если есть -- удалить. + +Представим, что у нас есть большая таблица ``, и мы хотим обновить её содержимое на новое. Вызов `$('table').html(новые данные)` перед вставкой новых данных аккуратно удалит старые: пробежит по всем ячейкам и проверит внутреннее хранилище. + +Если это большая таблица, то обработчики, скорее всего, стоят не на ячейках, а на самом элементе `
    `, то есть используется делегирование. А, значит, тратить время на проверку всех подэлементов ни к чему. + +Но jQuery-то об этом не знает! + +Чтобы "грязно" удалить элемент, без чистки, мы можем сделать это через "обычные" DOM-вызовы или воспользоваться методом detach(). Его официальное назначение -- в том, чтобы убрать элемент из DOM, но сохранить возможность для вставки (и, соответственно, оставить на нём все данные). А неофициальное -- быстро убрать элемент из DOM, без чистки. + +Возможен и промежуточный вариант: никто не мешает сделать `elem.detach()` и поместить вызов `elem.remove()` в `setTimeout`. В результате очистка будет происходить асинхронно и незаметно. + +## Итого + +
      +
    • Утечки памяти при использовании jQuery возможны, если через DOM-методы удалять элементы, к которым привязаны данные или обработчики.
    • +
    • Чтобы утечки не было, достаточно убедиться, что элемент удаляется при помощи методов jQuery.
    • +
    • Побочный эффект -- при удалении элементов jQuery должна проверить наличие данных для них. Это сильно замедляет процесс удаления большого поддерева DOM.
    • +
    • Если мы значем, что обработчиков и данных нет -- гораздо быстрее удалять элементы при помощи вызова `detach` или обычного DOM.
    • +
    + + diff --git a/3-more/4-optimize/2-memory-leaks-jquery/jquery-leak.view/index.html b/3-more/4-optimize/2-memory-leaks-jquery/jquery-leak.view/index.html new file mode 100644 index 00000000..13a18544 --- /dev/null +++ b/3-more/4-optimize/2-memory-leaks-jquery/jquery-leak.view/index.html @@ -0,0 +1,32 @@ + + + + + + + + +
    + + + +Утечка идёт... + + + + + diff --git a/3-more/5-compress/1-minification/article.md b/3-more/4-optimize/3-minification/article.md similarity index 100% rename from 3-more/5-compress/1-minification/article.md rename to 3-more/4-optimize/3-minification/article.md diff --git a/3-more/5-compress/1-minification/my.svg b/3-more/4-optimize/3-minification/my.svg old mode 100755 new mode 100644 similarity index 100% rename from 3-more/5-compress/1-minification/my.svg rename to 3-more/4-optimize/3-minification/my.svg diff --git a/3-more/5-compress/2-better-minification/article.md b/3-more/4-optimize/4-better-minification/article.md similarity index 76% rename from 3-more/5-compress/2-better-minification/article.md rename to 3-more/4-optimize/4-better-minification/article.md index 68b4debb..e5560ba9 100644 --- a/3-more/5-compress/2-better-minification/article.md +++ b/3-more/4-optimize/4-better-minification/article.md @@ -132,20 +132,27 @@ window.isIE = window.isIE || getBrowserVersion(); ## Убираем вызовы console.* -Минификатор имеет в своём распоряжении дерево кода и может удалить ненужные вызовы. Хотя по умолчанию в UglifyJS и GCC такого флага нет, код минификатора можно легко расширить, добавив эту возможность. +Минификатор имеет в своём распоряжении дерево кода и может удалить ненужные вызовы. +Для UglifyJS это делают опции компилятора:
      -
    • Для UglifyJS функция обхода дерева: +
    • `drop_debugger` -- убирает вызовы `debugger`.
    • +
    • `drop_console` -- убирает вызовы `console.*`.
    • +
    + +Можно написать и дополнительную функцию преобразования, которая убирает другие вызовы, например для `log.*`: ```js -//+ hide="Раскрыть функцию" +var uglify = require('uglify-js'); +var pro = uglify.uglify; + function ast_squeeze_console(ast) { var w = pro.ast_walker(), walk = w.walk, scope; return w.with_walkers({ "stat": function(stmt) { - if(stmt[0] === "call" && stmt[1][0] == "dot" && stmt[1][1] instanceof Array && stmt[1][1][0] == 'name' && stmt[1][1][1] == "console") { + if(stmt[0] === "call" && stmt[1][0] == "dot" && stmt[1][1] instanceof Array && stmt[1][1][0] == 'name' && stmt[1][1][1] == "log") { return ["block"]; } return ["stat", walk(stmt)]; @@ -161,22 +168,5 @@ function ast_squeeze_console(ast) { }; ``` -Полный код, использующий эту функцию и модуль uglify-js для сжатия с убиранием вызова: [myuglify.js](/files/tutorial/compress/myuglify.js). - -Вы можете добавить свои любимые опции и использовать его вместо поставляемого "из коробки". - -
  • В GCC соответствующие опции называются `stripNameSuffixes` и `stripTypePrefixes`, но они скрыты при запуске минификатора из командной строки или через веб-сервис. - -Чтобы их использовать, нужно либо поставить утилиту [plovr](http://plovr.com/), что эквивалентно стрельбе из пушки по воробьям, либо написать свой Java-код для вызова компилятора, который будет ставить опции. - -Выглядеть этот код может [примерно так](https://groups.google.com/d/msg/closure-compiler-discuss/qqdnzikzpWA/8cPHKIR1svgJ). -
  • - - -Аналогичным образом можно убрать и любой другой код, например вызовы вашего собственного логгера. - - - - - +Эту функцию следует вызвать на результате `parse`, и она пройдётся по дереву и удалит все вызовы `log.*`. diff --git a/3-more/5-compress/3-gcc-advanced-optimization/article.md b/3-more/4-optimize/5-gcc-advanced-optimization/article.md similarity index 100% rename from 3-more/5-compress/3-gcc-advanced-optimization/article.md rename to 3-more/4-optimize/5-gcc-advanced-optimization/article.md diff --git a/3-more/5-compress/4-gcc-check-types/article.md b/3-more/4-optimize/6-gcc-check-types/article.md similarity index 100% rename from 3-more/5-compress/4-gcc-check-types/article.md rename to 3-more/4-optimize/6-gcc-check-types/article.md diff --git a/3-more/5-compress/5-gcc-closure-library/article.md b/3-more/4-optimize/7-gcc-closure-library/article.md similarity index 100% rename from 3-more/5-compress/5-gcc-closure-library/article.md rename to 3-more/4-optimize/7-gcc-closure-library/article.md diff --git a/3-more/4-optimize/index.md b/3-more/4-optimize/index.md index 77df4229..66af82f4 100644 --- a/3-more/4-optimize/index.md +++ b/3-more/4-optimize/index.md @@ -1,2 +1,4 @@ # Оптимизация +Утечки памяти, увеличение скорости выполнения и загрузки скриптов. + diff --git a/3-more/5-compress/index.md b/3-more/5-compress/index.md deleted file mode 100644 index 9bee2987..00000000 --- a/3-more/5-compress/index.md +++ /dev/null @@ -1,2 +0,0 @@ -# Сжатие JavaScript - diff --git a/3-more/4-optimize/3-reflow/article.md b/archive/3-reflow/article.md similarity index 100% rename from 3-more/4-optimize/3-reflow/article.md rename to archive/3-reflow/article.md diff --git a/3-more/4-optimize/3-reflow/reflow.view/index.html b/archive/3-reflow/reflow.view/index.html old mode 100755 new mode 100644 similarity index 100% rename from 3-more/4-optimize/3-reflow/reflow.view/index.html rename to archive/3-reflow/reflow.view/index.html diff --git a/3-more/4-optimize/2-script-place-optimize/article.md b/archive/4-script-place-optimize/article.md similarity index 100% rename from 3-more/4-optimize/2-script-place-optimize/article.md rename to archive/4-script-place-optimize/article.md