JavaScript. Подробное руководство, 6-е издание, стр. 361

<b>// можно выполнить с помощью последовательности вызовов методов translate,rotate,translate </b>

<b>function rotateAbout(c,theta,x,у) {</b>

<b>  var ct = Math.cos(theta),</b>

<b>      st = Math.sin(theta);</b>

<b>  c.transform(ct, -st, st, ct, -x*ct-y*st+x, x*st-y*ct+y);</b>

<b>}</b>

Метод

<b>setTransform()</b>
принимает те же аргументы, что и метод
<b>transform(),</b>
но вместо преобразования текущей системы координат он выполняет преобразование системы координат по умолчанию и делает результат новой текущей системой координат. Метод
<b>setTransform()</b>
удобно использовать для временного возврата к системе координат по умолчанию:

<b>c.save(); // Сохранить текущую систему координат</b>

<b>с.setTransform(1,0,0,1,0,0): // Вернуться к системе координат по умолчанию </b>

<b>// Выполнить операции с использованием координат по умолчанию CSS-пикселов </b>

<b>c.restore(); // Восстановить сохраненную систему координат</b>

21.4.4.2. Примеры преобразований

Пример 21.6 демонстрирует мощь, которую дает возможность преобразования системы координат, где за счет рекурсивного применения методов

<b>translate(), rotate()</b>
и
<b>scale()</b>
реализовано рисование фракталов - снежинок Коха. Результат работы этого примера представлен на рис. 21.8, где показаны снежинки Коха с количеством уровней рекурсии 0, 1, 2, 3 и 4.

JavaScript. Подробное руководство, 6-е издание - i_060.jpg

Эти фигуры воспроизводятся весьма изящным программным кодом, но в нем используются рекурсивные преобразования системы координат, что делает его сложным для понимания. Даже если вы не собираетесь углубляться в изучение всех тонкостей примера, обратите все же внимание, что в нем имеется всего один вызов метода

<b>lineTo()</b>
. Каждый отдельный сегмент на рис. 21.8 рисуется следующим образом:

<b>с.lineТо(len, 0);</b>

Значение переменной 

<b>len</b>
не изменяется в ходе выполнения программы, поэтому позиция, ориентация и длина каждой линии определяется операциями смещения, вращения и масштабирования.

Пример 21.6. Рисование снежинок Коха посредством преобразований системы координат

<b>var deg = Math.PI/180; // Для преобразования градусов в радианы</b>

<b>// Рисует n-уровневый фрактал снежинки Коха в контексте холста с, левый нижний угол</b>

<b>// которого имеет координаты (х,у), а длина стороны равна len.</b>

<b>function snowflake(c, п, х, у, len) {</b>

<b>  c.saveO; // Сохранить текущее преобразование</b>

<b>  с.translated,у); // Сместить начало координат в начальную точку</b>

<b>  с.moveTo(0,0); // Новый фрагмент контура в новом начале координат</b>

<b>  leg(n); // Нарисовать первую ветвь снежинки</b>

<b>  с.rotate(-120*deg); // Поворот на 120 градусов против часовой стрелки</b>

<b>  leg(n); // Нарисовать вторую ветвь</b>

<b>  с.rotate(-120*deg); //Поворот</b>

<b>  leg(n); // Нарисовать последнюю ветвь</b>

<b>  с.closePath(); // Замкнуть фрагмент контура</b>

<b>  c.restoreO; // Восстановить прежнее преобразование</b>

<b>  // Рисует одну ветвь n-уровневой снежинки Коха. Эта функция оставляет</b>

<b>  // текущую позицию в конце нарисованной ветви и смещает начало координат так,</b>

<b>  // что текущая точка оказывается в позиции (0,0).</b>

<b>  // Это означает, что после рисования ветви можно вызвать rotate().</b>

<b>  function leg(n) {</b>

<b>    c.save(); // Сохранить текущее преобразование</b>

<b>    if (n == 0) { // Нерекурсивный случай:</b>

<b>      с.lineTo(len, 0); // Просто нарисовать горизонтальную линию</b>

<b>    } //</b>

<b>    else { // Рекурсивный случай: 4 подветви вида: \/</b>

<b>      с.scale(1/3,1/3); // Подветви в 3 раза меньше этой ветви</b>

<b>      leg(n-1); // Рекурсия для первой подветви</b>

<b>      с.rotate(60*deg); // Поворот на 60 градусов по часовой стрелке</b>

<b>      leg(n-1); // Вторая подветвь</b>

<b>      с.rotate(-120*deg); // Поворот на 120 градусов назад</b>

<b>      leg(n-1); // Третья подветвь</b>

<b>      с.rotate(60*deg); // Поворот обратно к началу</b>

<b>      leg(п-1); // Последняя подветвь</b>

<b>    }</b>

<b>    c.restore(); // Восстановить преобразование</b>

<b>    с.translate(len, 0); // Но сместить в конец ветви (0,0)</b>

<b>  }</b>

<b>}</b>

<b>snowf1аке(с,0,5,115,125); // Снежинка нулевого уровня является</b>

<b>                          // равносторонним треугольником</b>