Фракталы - это бесконечные узоры, созданные повторяющимися математическими уравнениями. Мы нарисуем один из самых известных фракталов, используя только Vanilla JS и HTML5 Canvas API.Фракталы - это бесконечные узоры, созданные повторяющимися математическими уравнениями. Мы нарисуем один из самых известных фракталов, используя только Vanilla JS и HTML5 Canvas API.

Программирование фрактального дерева с помощью JavaScript и HTML5

2025/10/11 03:00

\ Фракталы, эти загадочные фигуры, которые повсюду, но не видны неподготовленному глазу. Сегодня мы нарисуем один из самых известных фракталов, используя только Vanilla JS и HTML5 Canvas API. Давайте программировать!

Что вы узнаете

  • Что такое фрактальное дерево?
  • Написание фрактального дерева на Vanilla JS
  • За пределами фрактального дерева

Что такое фрактальное дерево?

Чтобы определить фрактальное дерево, сначала мы должны знать определение фрактала, конечно.

Фракталы — это бесконечные узоры, созданные повторяющимися математическими уравнениями, которые в любом масштабе, на любом уровне увеличения выглядят примерно одинаково. Другими словами, геометрический объект, основная структура которого, грубая или фрагментированная, повторяется в разных масштабах.

Так что если мы разделим фрактал, мы увидим уменьшенную копию целого.

Бенуа Мандельброт, который придумал термин "фрактал" в 1975 году, сказал:

\

\ Довольно ясно, правда?

Вот несколько примеров:

Animated Von Koch Curve

\ Animated Sierpinski Carpet

Теперь, что такое фрактальное дерево?

Представьте ветвь, и ветви, выходящие из нее, а затем две ветви, выходящие из каждой ветви, и так далее... вот как выглядит фрактальное дерево.

Его форма происходит от треугольника Серпинского (или салфетки Серпинского).

Как видите, одно становится другим при изменении угла между ветвями:

From Sierpinski Triangle to Fractal

Сегодня мы закончим с фигурой, похожей на конечную форму этого GIF.

Написание фрактального дерева на Vanilla JS

Прежде всего, вот конечный продукт (вы можете настраивать его по ходу дела):

Final Fractal Tree

Теперь давайте нарисуем это, шаг за шагом.

Прежде всего, мы инициализируем наш файл index.html с холстом любых разумных размеров и тегом script, где будет весь наш JS-код.

<!doctype html> <html lang="en">   <head>     <meta charset="UTF-8" />   </head>   <body>     <canvas id="my_canvas" width="1000" height="800"></canvas>     <script></script>   </body> </html> 

Затем мы начинаем писать наш JavaScript.

Мы инициализируем наш элемент canvas в JS, получая к нему доступ через переменную myCanvas и создавая 2D-контекст рендеринга с переменной ctx (context).

<!doctype html> <html lang="en">   <head>     <meta charset="UTF-8" />   </head>   <body>     <canvas id="my_canvas" width="1000" height="800"></canvas>     <script>       var myCanvas = document.getElementById("my_canvas");       var ctx = myCanvas.getContext("2d");     </script>   </body> </html> 

Итак, метод getContext добавляет свойства и методы, которые позволяют рисовать, в данном случае, в 2D.

Теперь пришло время подумать. Как мы можем определить алгоритм для рисования фрактального дерева? Хм... 🤔

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

Другими словами, когда ветвь достаточно длинная, прикрепите к ней две меньшие ветви. Повторите.

Это звучит так, как будто мы должны где-то использовать рекурсивное выражение, не так ли?

Вернемся к коду, теперь мы определяем нашу функцию fractalTree, которая должна принимать как минимум четыре аргумента: координаты X и Y, где начинается ветвь, длину ветви и ее угол.

Внутри нашей функции мы начинаем рисование с метода beginPath(), а затем сохраняем состояние холста с помощью метода save().

<!doctype html> <html lang="en">   <head>     <meta charset="UTF-8" />   </head>   <body>     <canvas id="my_canvas" width="1000" height="800"></canvas>     <script>       var myCanvas = document.getElementById("my_canvas");       var ctx = myCanvas.getContext("2d");       function draw(startX, startY, len, angle) {           ctx.beginPath();           ctx.save();       }     </script>   </body> </html> 

Метод beginPath часто используется, когда вы начинаете новую линию или фигуру, имеющую фиксированный стиль, например, одинаковый цвет по всей линии или одинаковую ширину. Метод save просто сохраняет все состояние холста, помещая текущее состояние в стек.

Теперь мы нарисуем наше фрактальное дерево, рисуя линию (ветвь), вращая холст, рисуя следующую ветвь и так далее. Это выглядит так (я объясню каждый метод под примером кода):

<!doctype html> <html lang="en">   <head>     <meta charset="UTF-8" />   </head>   <body>     <canvas id="my_canvas" width="1000" height="800"></canvas>     <script>       var myCanvas = document.getElementById("my_canvas");       var ctx = myCanvas.getContext("2d");       function draw(startX, startY, len, angle) {           ctx.beginPath();           ctx.save();            ctx.translate(startX, startY);           ctx.rotate(angle * Math.PI/180);           ctx.moveTo(0, 0);           ctx.lineTo(0, -len);           ctx.stroke();            if(len < 10) {               ctx.restore();               return;           }            draw(0, -len, len*0.8, -15);           draw(0, -len, len*0.8, +15);            ctx.restore();       }       draw(400, 600, 120, 0)     </script>   </body> </html> 

Итак, сначала мы добавляем три метода: translate, rotate и moveTo, которые "перемещают" холст, его начало и наш "карандаш", чтобы мы могли нарисовать ветвь под нужным углом. Это как если бы мы рисовали ветвь, затем центрировали эту ветвь (перемещая весь холст), а затем рисовали новую ветвь от конца нашей предыдущей ветви.

Последние два метода перед оператором if — это lineTo и stroke; первый добавляет прямую линию к текущему пути, а второй ее отображает. Вы можете думать об этом так: lineTo дает приказ, а stroke его выполняет.

Теперь у нас есть оператор if, который указывает, когда остановить рекурсию, когда прекратить рисование. Метод restore, как указано в документации MDN, "восстанавливает последнее сохраненное состояние холста, извлекая верхнюю запись из стека состояний рисования".

После оператора if у нас есть рекурсивный вызов и еще один вызов метода restore. А затем вызов функции, которую мы только что закончили.

Теперь запустите код в вашем браузере. Вы увидите, наконец, фрактальное дерево!

Fractal Tree First Iteration

Потрясающе, правда? Теперь давайте сделаем его еще лучше.

Мы добавим новый параметр в нашу функцию draw, branchWidth, чтобы сделать наше фрактальное дерево более реалистичным.

<!doctype html> <html lang="en">   <head>     <meta charset="UTF-8" />   </head>   <body>     <canvas id="my_canvas" width="1000" height="800"></canvas>     <script>       var myCanvas = document.getElementById("my_canvas");       var ctx = myCanvas.getContext("2d");       function draw(startX, startY, len, angle, branchWidth) {           ctx.lineWidth = branchWidth;            ctx.beginPath();           ctx.save();            ctx.translate(startX, startY);           ctx.rotate(angle * Math.PI/180);           ctx.moveTo(0, 0);           ctx.lineTo(0, -len);           ctx.stroke();            if(len < 10) {               ctx.restore();               return;           }            draw(0, -len, len*0.8, angle-15, branchWidth*0.8);           draw(0, -len, len*0.8, angle+15, branchWidth*0.8);            ctx.restore();       }       draw(400, 600, 120, 0, 10)     </script>   </body> </html> 

Таким образом, в каждой итерации мы делаем каждую ветвь тоньше. Я также изменил параметр угла в рекурсивном вызове, чтобы сделать дерево более "открытым".

Теперь давайте добавим немного цвета! И тени, почему бы и нет.

<!doctype html> <html lang="en">   <head>     <meta charset="UTF-8" />   </head>   <body>     <canvas id="my_canvas" width="1000" height="800"></canvas>     <script>       var myCanvas = document.getElementById("my_canvas");       var ctx = myCanvas.getContext("2d");       function draw(startX, startY, len, angle, branchWidth) {           ctx.lineWidth = branchWidth;            ctx.beginPath();           ctx.save();            ctx.strokeStyle = "green";           ctx.fillStyle = "green";            ctx.translate(startX, startY);           ctx.rotate(angle * Math.PI/180);           ctx.moveTo(0, 0);           ctx.lineTo(0, -len);           ctx.stroke();            ctx.shadowBlur = 15;           ctx.shadowColor = "rgba(0,0,0,0.8)";            if(len < 10) {               ctx.restore();               return;           }            draw(0, -len, len*0.8, angle-15, branchWidth*0.8);           draw(0, -len, len*0.8, angle+15, branchWidth*0.8);            ctx.restore();       }       draw(400, 600, 120, 0, 10)     </script>   </body> </html> 

Оба метода цвета понятны сами по себе (strokeStyle и fillStyle). Также и методы тени, shadowBlur и shadowColor.

И это все! Сохраните файл и откройте его в браузере, чтобы увидеть конечный продукт.

Теперь я призываю вас поиграть с кодом

Отказ от ответственности: Статьи, размещенные на этом веб-сайте, взяты из общедоступных источников и предоставляются исключительно в информационных целях. Они не обязательно отражают точку зрения MEXC. Все права принадлежат первоисточникам. Если вы считаете, что какой-либо контент нарушает права третьих лиц, пожалуйста, обратитесь по адресу service@support.mexc.com для его удаления. MEXC не дает никаких гарантий в отношении точности, полноты или своевременности контента и не несет ответственности за любые действия, предпринятые на основе предоставленной информации. Контент не является финансовой, юридической или иной профессиональной консультацией и не должен рассматриваться как рекомендация или одобрение со стороны MEXC.

Вам также может быть интересно

Саудовская Аравия выдает две лицензии чартерным авиакомпаниям

Саудовская Аравия выдает две лицензии чартерным авиакомпаниям

Саудовская Аравия выдала лицензии национальной чартерной авиакомпании двум консорциумам в рамках плана по достижению 100 миллионов ежегодных посетителей к 2030 году. Главное управление гражданской авиации (Gaca) выдало лицензии альянсам под руководством Jazeera Airways и BeOnd Aviation, сообщило ведомство в заявлении. Двум альянсам будет разрешено осуществлять деятельность [...]
Поделиться
Agbi2025/12/11 12:13