Перейти к основному содержимому

SVG — рисунки кодом

Готовые одностраничные примеры: скопировали HTML в файл, открыли в браузере — картинка уже на экране. Ищете «нарисовать квадрат svg», «svg треугольник код», «svg домик», «svg цветок», «снежинка svg», «svg звезда», «svg анимация» — ниже код с разбором каждой важной строки, как в примерах Turtle и p5.js.

Под каждым блоком — зачем атрибут, как браузер рисует фигуру, типичные ошибки новичков и что поменять для эксперимента.


Основы рисования в SVG

SVG (Scalable Vector Graphics) — язык разметки для векторных картинок. Фигура описывается текстом: координаты, цвета, дуги. Браузер масштабирует рисунок без «лесенки» на Retina и на больших экранах. SVG встраивают прямо в HTML, сохраняют в файл .svg, стилизуют через CSS и оживляют анимацией.

С чего начать

Теория по тегу <svg>справочник HTML, раздел SVG. Обзор формата — основные языки разметки. Тот же стиль «черепашки», но на Python — примеры Turtle; на JavaScript с холстом — p5.js. Каркас страницы — HTML + CSS — готовые макеты. Движение и плавные переходы — CSS-анимации.

Кому подойдёт эта страница

Школьникам — квадрат, домик, снежинка для урока информатики или проекта.
Студентам — иконки, диаграммы, инфографика для лабораторной и портфолио.
Самоучкам — первый векторный рисунок в браузере без Photoshop и без установки Python.
Кто гуглит перед контрольной — короткий рабочий код вместо десяти вкладок с обрывками без пояснений.

Загрузка HTML-песочницы…

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


Как запустить пример за 30 секунд

  1. Скопируйте весь блок (от <!DOCTYPE html> до </html>).
  2. Вставьте в Блокнот / VS Code / Notepad++.
  3. Сохраните как figure.html (расширение .html, не .txt).
  4. Откройте двойным щелчком или перетащите в Chrome / Edge / Firefox.
  5. Пустой экран — проверьте, что скопировали закрывающий </svg> и </html>.
ГдеПлюсы
Файл .html на дискеРаботает офлайн после сохранения
Inline в HTMLОдин файл, CSS и JS рядом с рисунком
Отдельный icon.svgИконка для сайта, <img src="icon.svg" alt="…">
Редактор вышеБыстро править без сохранения на диск

Базовые термины

ТерминПростыми словами
viewBoxВнутренняя система координат: «логический» холст, который браузер масштабирует под width/height
width, heightРазмер картинки на экране (px, %, em)
fillЦвет заливки (none — прозрачная внутренность)
strokeЦвет контура
stroke-widthТолщина линии
<rect>Прямоугольник
<circle>Круг (cx, cy — центр, r — радиус)
<polygon>Многоугольник по списку точек points="x1,y1 x2,y2 …"
<line>Отрезок от (x1,y1) до (x2,y2)
<path d="…">Произвольная линия, дуга, кривая Безье
<g>Группа элементов (удобно двигать и вращать вместе)
transformСдвиг, поворот, масштаб (translate, rotate, scale)

Какую фигуру выбрать

Вы ищете…Пример нижеИдея
Квадрат, прямоугольникКвадрат<rect> или <polygon> из 4 точек
ТреугольникТреугольник<polygon> с 3 вершинами
Дом, крышаДомик<rect> + треугольник
ЦветокЦветокКруги по окружности или цикл в JS
СнежинкаСнежинкаЛучи <line> + rotate
СердцеСердце<path> с кривыми Безье
Звезда, n-угольникМногоугольникиФормула углов или готовые points
Шахматная доскаСеткаДвойной цикл for
Дерево, фракталДерево, КохРекурсия в JavaScript
ДвижениеАнимацияCSS @keyframes или SMIL

Система координат

В SVG точка (0, 0)левый верхний угол viewBox. Ось X растёт вправо, Y — вниз (как на экране Turtle и в Canvas). Центр холста 200×200: cx="100" cy="100" для круга или transform="translate(100 100)" для группы.

Связь с Turtle: в Python Y часто «вверх», на экране черепашки — как в SVG. В SVG вы сразу задаёте координаты точек, без команд forward и left.


Как работать с примерами

  1. Сначала запустите код как есть — убедитесь, что в браузере появилась картинка.
  2. Меняйте одно значение за раз (width, цвет, координату).
  3. Сломали — верните исходник из статьи.
  4. Готовый SVG вставьте в макет страницы — блок <svg> внутри <body>.
Типичные ошибки новичков
  • Белый экран — забыли закрыть тег </svg> или сохранили файл как .txt.
  • Фигура не видна — fill="none" и нет stroke; или координаты за пределами viewBox.
  • «Квадрат стал прямоугольником» — разные width и height у <rect>.
  • Градиент не работает — url(#id) ссылается на id из другого SVG; <defs> должны быть в том же <svg>.
  • JS не рисует — скрипт выполняется до того, как DOM готов; ставьте <script> в конец <body> или используйте DOMContentLoaded.

Обязательный каркас

Любой статичный рисунок строится по схеме: HTML-страница → тег <svg> → фигуры внутри.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>SVG — рисунок</title>
<style>
body {
margin: 0;
min-height: 100dvh;
display: grid;
place-items: center;
background: #f8fafc;
font-family: system-ui, sans-serif;
}
svg {
background: #fff;
border-radius: 12px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
}
</style>
</head>
<body>
<svg width="320" height="320" viewBox="0 0 320 320" role="img" aria-label="Мой рисунок">
<!-- здесь фигуры -->
</svg>
</body>
</html>

Разбор по строкам.

ФрагментСмысл
<!DOCTYPE html>Режим HTML5 — браузер рисует страницу предсказуемо
<meta charset="UTF-8">Кириллица в <title> и aria-label
viewportНа телефоне страница не «уменьшенный десктоп»
body &#123; margin: 0 &#125;Убирает белую полоску у края окна
display: grid; place-items: centerSVG по центру экрана
min-height: 100dvhМинимум на всю высоту; dvh учитывает панель браузера на телефоне
width="320" height="320"Размер картинки на странице в пикселях
viewBox="0 0 320 320"Логический холст: от (0,0) до (320,320); при равных width и viewBox — 1 unit = 1 px
role="img" + aria-labelСкринридер озвучит подпись вместо «пустого» SVG
<!-- здесь фигуры -->Комментарий; браузер его не рисует

Минимальный фрагмент — только SVG без HTML-обёртки (для вставки в готовую страницу):

<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<!-- фигуры -->
</svg>
АтрибутЗачем
xmlns="http://www.w3.org/2000/svg"Обязателен в отдельном файле .svg; в HTML можно опустить
viewBox="0 0 200 200"Если потом увеличите width="400", картинка масштабируется без потери чёткости

Стартовые фигуры

Пять типов, которые чаще всего ищут вместе с Turtle и p5.js: квадрат, треугольник, домик, цветок, снежинка. Дальше — сердце, сетки, фракталы и анимация.


Квадрат на SVG (аналог forward + left в Turtle)

Четыре стороны одинаковой длины. В Turtle вы четыре раза forward(100) и left(90). В SVG проще сказать браузеру: «нарисуй прямоугольник 100×100 в таких координатах».

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Квадрат SVG</title>
<style>
body { margin: 0; display: grid; place-items: center; min-height: 100dvh; background: #f1f5f9; }
</style>
</head>
<body>
<svg width="240" height="240" viewBox="0 0 240 240" role="img" aria-label="Квадрат">
<rect x="70" y="70" width="100" height="100"
fill="none" stroke="#1e293b" stroke-width="3"/>
</svg>
</body>
</html>

Разбор:

  • <rect> — один тег вместо четырёх отрезков; браузер сам замыкает контур.
  • x="70" y="70"левый верхний угол квадрата (не центр!).
  • width="100" height="100" — сторона 100 px; для квадрата оба числа одинаковые.
  • fill="none" — внутри прозрачно; виден только контур.
  • stroke="#1e293b" — цвет линии (тёмно-серый).
  • stroke-width="3" — толщина контура 3 px.

Почему x=70, y=70? Холст 240×240. Квадрат 100×100. Чтобы центрировать: (240 − 100) / 2 = 70.

Что изменить: width="150" height="150" и x="45" y="45" — больший квадрат по центру; fill="#93c5fd" — голубая заливка вместо пустоты.

Аналог в Turtle: квадрат forward/left — там четыре команды; здесь одна строка <rect>.

Вариант через <polygon> — удобно, если потом нужно повернуть фигуру через transform="rotate(...)":

<polygon points="70,70 170,70 170,170 70,170"
fill="none" stroke="#1e293b" stroke-width="3"/>
pointsУгол квадрата
70,70левый верхний
170,70правый верхний
170,170правый нижний
70,170левый нижний

Точки перечисляют по порядку обхода — браузер соединяет их линиями и замыкает контур.


Равносторонний треугольник

Три вершины — три пары координат в points. В Turtle: цикл for i in range(3) с left(120).

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Треугольник SVG</title>
<style>
body { margin: 0; display: grid; place-items: center; min-height: 100dvh; background: #f1f5f9; }
</style>
</head>
<body>
<svg width="240" height="240" viewBox="0 0 240 240" role="img" aria-label="Равносторонний треугольник">
<polygon points="120,50 190,170 50,170"
fill="#fef08a" stroke="#ca8a04" stroke-width="3"
stroke-linejoin="round"/>
</svg>
</body>
</html>

Разбор:

  • 120,50верхняя вершина по центру холста (x=120 — середина 240).
  • 190,170 и 50,170 — нижние углы; обе на y=170, симметрично относительно центра.
  • fill="#fef08a" — жёлтая заливка.
  • stroke="#ca8a04" — контур темнее заливки — фигура читается на любом фоне.
  • stroke-linejoin="round" — углы слегка скруглены (без «острых иголок» на стыках линий).

Связь с математикой: у равностороннего треугольника все стороны равны; в Turtle поворот между сторонами — 120° (внешний угол).

Что изменить: поднять вершину — 120,30 вместо 120,50 (треугольник выше); fill="none" — только контур, как у квадрата выше.

Аналог в Turtle: треугольник for + left(120).


Домик (стены + крыша + дверь)

Три простые фигуры слоями. Сначала «дальние» части, потом ближние — как в Turtle вы рисуете стены, потом крышу.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Домик SVG</title>
<style>
body { margin: 0; display: grid; place-items: center; min-height: 100dvh; background: #e0f2fe; }
</style>
</head>
<body>
<svg width="260" height="260" viewBox="0 0 260 260" role="img" aria-label="Домик">
<!-- стены -->
<rect x="80" y="120" width="100" height="90" fill="#fde68a" stroke="#92400e" stroke-width="2"/>
<!-- крыша -->
<polygon points="60,120 130,60 200,120" fill="#ef4444" stroke="#991b1b" stroke-width="2"/>
<!-- дверь -->
<rect x="115" y="155" width="30" height="55" fill="#78350f" stroke="#451a03" stroke-width="1"/>
</svg>
</body>
</html>

Разбор:

ЭлементТегЧто задаёт
Стены<rect x="80" y="120" width="100" height="90">Прямоугольник: левый верх (80,120), ширина 100, высота 90
Крыша<polygon points="60,120 130,60 200,120">Треугольник: основание на y=120, вершина на y=60
Дверь<rect x="115" y="155" width="30" height="55">Узкий прямоугольник поверх стен
  • Порядок в файле важен: то, что написано ниже, рисуется поверх (дверь перекрывает стены).
  • Крыша шире стен (60…200 против 80…180) — классический «свес».
  • <!-- стены --> — комментарий для себя; в браузере не виден.

Что изменить: fill="#ef4444" у стен — красный дом; добавьте <circle cx="200" cy="80" r="25" fill="#fef08a"/> — солнце в углу.

Аналог в Turtle: домик left + forward.


Простой цветок из кругов

Шесть лепестков — шесть <circle> вокруг центра. В Turtle: t.circle(30) и t.right(60) шесть раз.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Цветок SVG</title>
<style>
body { margin: 0; display: grid; place-items: center; min-height: 100dvh; background: #fdf2f8; }
</style>
</head>
<body>
<svg width="260" height="260" viewBox="0 0 260 260" role="img" aria-label="Цветок из кругов">
<g transform="translate(130 130)">
<!-- 6 лепестков по кругу радиуса 50 -->
<circle cx="50" cy="0" r="22" fill="#f472b6"/>
<circle cx="25" cy="43" r="22" fill="#f472b6"/>
<circle cx="-25" cy="43" r="22" fill="#f472b6"/>
<circle cx="-50" cy="0" r="22" fill="#f472b6"/>
<circle cx="-25" cy="-43" r="22" fill="#f472b6"/>
<circle cx="25" cy="-43" r="22" fill="#f472b6"/>
<!-- серединка -->
<circle cx="0" cy="0" r="18" fill="#facc15"/>
</g>
</svg>
</body>
</html>

Разбор:

  • <g transform="translate(130 130)">группа с переносом начала координат в центр холста (130 = половина 260). Все cx/cy внутри считаются от центра цветка.
  • cx="50" cy="0" — центр лепестка на расстоянии 50 px вправо от середины.
  • r="22" — радиус лепестка (не диаметр! В SVG у <circle> именно радиус).
  • Остальные лепестки — те же точки на окружности: углы 60°, 120°, 180°, 240°, 300°.
  • Жёлтый <circle cx="0" cy="0" r="18"> рисуется последним — поверх лепестков.

Откуда числа 25 и 43? Для угла 60°: x = 50·cos(60°) ≈ 25, y = 50·sin(60°) ≈ 43. Можно не запоминать — см. вариант с циклом ниже.

Что изменить: r="30" у лепестков — крупнее; добавьте седьмой <circle> с другим cx,cy — эксперимент с числом лепестков.

Аналог в Turtle: красный цветок circle + right(60).


Цветок через цикл JavaScript (без копипаста координат)

Тот же рисунок, но координаты считает цикл — как for i in range(6) в Python.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Цветок SVG + JS</title>
<style>
body { margin: 0; display: grid; place-items: center; min-height: 100dvh; background: #fdf2f8; }
</style>
</head>
<body>
<svg width="260" height="260" viewBox="0 0 260 260">
<g transform="translate(130 130)" id="flower"></g>
</svg>
<script>
const g = document.getElementById('flower');
const petals = 6;
const orbit = 50;
const petalR = 22;

for (let i = 0; i < petals; i++) {
const deg = i * (360 / petals);
const rad = (deg * Math.PI) / 180;
const cx = orbit * Math.cos(rad);
const cy = orbit * Math.sin(rad);

const c = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
c.setAttribute('cx', cx);
c.setAttribute('cy', cy);
c.setAttribute('r', petalR);
c.setAttribute('fill', '#f472b6');
g.appendChild(c);
}

const center = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
center.setAttribute('r', 18);
center.setAttribute('fill', '#facc15');
g.appendChild(center);
</script>
</body>
</html>

Разбор по строкам JavaScript:

СтрокаСмысл
document.getElementById('flower')Находим группу <g id="flower">, куда добавим круги
createElementNS('…svg', 'circle')SVG живёт в своём namespace — обычный createElement может не сработать
deg = i * (360 / petals)Угол i-го лепестка: 0°, 60°, 120°…
Math.cos(rad) / Math.sin(rad)Координаты точки на окружности радиуса orbit
setAttribute('cx', cx)Записываем атрибут так же, как в HTML-разметке
g.appendChild(c)Добавляем круг в SVG-дерево — браузер сразу рисует

Что изменить: petals = 8 и orbit = 55 — цветок с восемью лепестками; fill на #a855f7' — фиолетовый.


Простая снежинка

Восемь лучей из центра. В Turtle: forward(50), backward(50), right(45) в цикле.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Снежинка SVG</title>
<style>
body { margin: 0; display: grid; place-items: center; min-height: 100dvh; background: #0f172a; }
</style>
</head>
<body>
<svg width="260" height="260" viewBox="0 0 260 260" role="img" aria-label="Снежинка">
<g transform="translate(130 130)" stroke="#67e8f9" stroke-width="3" stroke-linecap="round">
<line x1="0" y1="-70" x2="0" y2="70"/>
<line x1="-70" y1="0" x2="70" y2="0"/>
<line x1="-49" y1="-49" x2="49" y2="49"/>
<line x1="49" y1="-49" x2="-49" y2="49"/>
<line x1="0" y1="-70" x2="0" y2="70" transform="rotate(22.5)"/>
<line x1="0" y1="-70" x2="0" y2="70" transform="rotate(45)"/>
<line x1="0" y1="-70" x2="0" y2="70" transform="rotate(67.5)"/>
<line x1="0" y1="-70" x2="0" y2="70" transform="rotate(90)"/>
</g>
</svg>
</body>
</html>

Разбор:

  • translate(130 130) — центр снежинки в середине холста.
  • stroke и stroke-width на <g>наследуются всеми <line> внутри (DRY: не повторяем на каждой линии).
  • stroke-linecap="round" — концы лучей скруглены.
  • <line x1="0" y1="-70" x2="0" y2="70"/> — вертикальный луч длиной 140 px через центр; отрицательный Y — вверх от центра.
  • Диагонали: -49 и 49 — это 70 / √2 ≈ 49 (концы на окружности радиуса 70).
  • transform="rotate(45)" — тот же шаблон луча, повёрнутый на 45° вокруг начала группы (центра).

Что изменить: -70-100 — длиннее лучи; только 4 луча — оставьте первые две строки <line>.

Через цикл (8 лучей, как for i in range(8)):

<g transform="translate(130 130)" stroke="#67e8f9" stroke-width="3" id="flakes"></g>
<script>
const box = document.getElementById('flakes');
for (let i = 0; i < 8; i++) {
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', 0);
line.setAttribute('y1', -70);
line.setAttribute('x2', 0);
line.setAttribute('y2', 70);
line.setAttribute('transform', `rotate(${i * 45})`);
box.appendChild(line);
}
</script>

i * 45 — поворот 0°, 45°, 90°… — ровно 360° / 8.

Аналог в Turtle: снежинка forward/backward/right.


Сердце

Сложная форма из одного <path>. Команды в атрибуте d читаются как «язык чертежника».

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Сердце SVG</title>
<style>
body { margin: 0; display: grid; place-items: center; min-height: 100dvh; background: #fff1f2; }
</style>
</head>
<body>
<svg width="240" height="240" viewBox="0 0 240 240" role="img" aria-label="Сердце">
<path d="M 120 200
C 120 160, 70 130, 70 90
C 70 60, 95 45, 120 65
C 145 45, 170 60, 170 90
C 170 130, 120 160, 120 200 Z"
fill="#ef4444" stroke="#991b1b" stroke-width="2"/>
</svg>
</body>
</html>

Команды path (мини-шпаргалка):

БукваНазваниеДействие
M x yMoveПереместить «перо», не рисуя
C x1 y1, x2 y2, x yCubic BezierКривая к (x,y) с двумя контрольными точками
L x yLineПрямая (в этом примере не используется)
ZCloseЗамкнуть контур до первой точки

Разбор контура:

  • M 120 200 — старт в нижней точке сердца (острие).
  • Первая C — левая дуга вверх.
  • Вторая C — левый «бугор».
  • Третья C — правый «бугор» (симметрия).
  • Четвёртая C — спуск к острию.
  • Z — линия обратно к M.

Что изменить: fill="#ec4899" — розовое сердце; уберите stroke — только заливка.

Аналог в Turtle: сердце circle + left.


Примеры фигур

Ниже — функции и паттерны для учебных задач, иконок и орнаментов. Каждый блок можно вставить в каркас вместо комментария «здесь фигуры».


1. Базовые многоугольники

1.1. Правильный n-угольник

Формула вершин на окружности — обобщение треугольника и шестиугольника.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>n-угольник SVG</title>
<style>
body { margin: 0; display: grid; place-items: center; min-height: 100dvh; background: #f8fafc; }
</style>
</head>
<body>
<svg width="300" height="300" viewBox="0 0 300 300" id="stage"></svg>
<script>
function regularPolygon(n, cx, cy, radius) {
const pts = [];
for (let i = 0; i < n; i++) {
const angle = (i / n) * 2 * Math.PI - Math.PI / 2;
pts.push(`${cx + radius * Math.cos(angle)},${cy + radius * Math.sin(angle)}`);
}
return pts.join(' ');
}

const svg = document.getElementById('stage');
const poly = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
poly.setAttribute('points', regularPolygon(8, 150, 150, 100));
poly.setAttribute('fill', '#c4b5fd');
poly.setAttribute('stroke', '#5b21b6');
poly.setAttribute('stroke-width', '2');
svg.appendChild(poly);
</script>
</body>
</html>

Разбор функции regularPolygon:

ПараметрСмысл
nЧисло сторон (3 — треугольник, 6 — шестиугольник, 8 — восьмиугольник)
cx, cyЦентр фигуры
radiusРасстояние от центра до вершины
(i / n) * 2 * Math.PIУгол i-й вершины в радианах (полный оборот 2π)
- Math.PI / 2Поворот на −90° — чтобы первая вершина была сверху, а не справа
pts.join(' ')Строка для атрибута points: "x1,y1 x2,y2 …"

Что изменить: regularPolygon(5, 150, 150, 100) — пятиугольник; regularPolygon(3, …) — снова треугольник, но через формулу.


1.2. Звезда

Десять точек — чередование «внешнего» и «внутреннего» радиуса.

<svg width="280" height="280" viewBox="0 0 280 280" role="img" aria-label="Звезда">
<polygon points="140,30 165,110 250,110 182,160 207,240 140,195 73,240 98,160 30,110 115,110"
fill="#fde047" stroke="#a16207" stroke-width="2"/>
</svg>

Генерация координат (удобно менять число лучей):

function starPoints(cx, cy, outerR, innerR, spikes) {
const pts = [];
const step = Math.PI / spikes;
for (let i = 0; i < 2 * spikes; i++) {
const r = i % 2 === 0 ? outerR : innerR;
const a = i * step - Math.PI / 2;
pts.push(`${cx + r * Math.cos(a)},${cy + r * Math.sin(a)}`);
}
return pts.join(' ');
}
// starPoints(140, 140, 110, 45, 5) — пятиконечная звезда

Разбор:

  • i % 2 === 0 ? outerR : innerR — чётные шаги дальше от центра, нечётные ближе — «зубцы» звезды.
  • 2 * spikes итераций — по две точки на каждый луч.

Что изменить: spikes = 6 — шестиконечная звезда; innerR ближе к outerR — «толстая» звезда.


2. Кривые и path

2.1. Спираль Архимеда

Точки по формуле r = a + b·θ; соединяются отрезками <path>.

<svg width="320" height="320" viewBox="-160 -160 320 320">
<path id="spiral" fill="none" stroke="#2563eb" stroke-width="2"/>
</svg>
<script>
let d = 'M 0 0';
for (let deg = 0; deg <= 720; deg += 2) {
const rad = (deg * Math.PI) / 180;
const r = 4 + 0.35 * deg;
d += ` L ${r * Math.cos(rad)} ${r * Math.sin(rad)}`;
}
document.getElementById('spiral').setAttribute('d', d);
</script>

Разбор:

  • viewBox="-160 -160 320 320" — центр (0,0) в середине картинки (отрицательные координаты слева и сверху).
  • M 0 0 — старт в центре.
  • L x y — линия к следующей точке спирали.
  • deg <= 720 — два полных оборота (360° × 2).
  • r = 4 + 0.35 * deg — чем больше угол, тем дальше от центра (спираль расширяется).

Что изменить: 0.350.15 — более плотная спираль; 7201080 — три оборота.


2.2. Полярная «роза»

Уравнение r = a·cos(k·θ) в декартовых координатах.

<svg width="320" height="320" viewBox="-160 -160 320 320">
<path id="rose" fill="none" stroke="#db2777" stroke-width="2"/>
</svg>
<script>
const k = 5;
let d = '';
for (let deg = 0; deg <= 360; deg += 1) {
const rad = (deg * Math.PI) / 180;
const r = 100 * Math.cos(k * rad);
const x = r * Math.cos(rad);
const y = r * Math.sin(rad);
d += (deg === 0 ? 'M' : 'L') + ` ${x} ${y}`;
}
document.getElementById('rose').setAttribute('d', d + ' Z');
</script>

Разбор:

  • k = 5пять лепестков (при нечётном k).
  • Math.cos(k * rad) — радиус «пульсирует» — то ноль, то максимум → лепестки.
  • deg === 0 ? 'M' : 'L' — первая точка Move, остальные Line.
  • ' Z' в конце — замкнуть контур (для заливки можно добавить fill="#fce7f3").

3. Заливки и градиенты

Небо и солнце — типичный учебный пример «как сделать градиент svg».

<svg width="280" height="200" viewBox="0 0 280 200" role="img" aria-label="Небо и солнце">
<defs>
<linearGradient id="sky" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#38bdf8"/>
<stop offset="100%" stop-color="#1e3a8a"/>
</linearGradient>
<radialGradient id="sun" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#fef08a"/>
<stop offset="100%" stop-color="#f97316"/>
</radialGradient>
</defs>
<rect width="280" height="200" fill="url(#sky)"/>
<circle cx="220" cy="50" r="35" fill="url(#sun)"/>
</svg>

Разбор:

ЭлементСмысл
<defs>Ресурсы «в запасе» — сами не рисуются, пока на них не сослались
linearGradient id="sky"Имя для ссылки url(#sky); id уникален внутри SVG
x1="0" y1="0" x2="0" y2="1"Градиент сверху вниз (y2=1 — нижний край)
<stop offset="0%">Цвет в начале градиента
fill="url(#sky)"Залить прямоугольник не цветом, а градиентом
radialGradientКруговой градиент — солнце «светится» из центра

Что изменить: поменяйте stop-color — другое небо; r="50" у солнца — больше диск.


4. Сетки и орнаменты

4.1. Шахматная доска (как в Turtle — сетка квадратов)

Двойной цикл — классика урока «вложенные циклы».

<svg width="240" height="240" viewBox="0 0 240 240" role="img" aria-label="Шахматная доска">
<g id="board"></g>
<script>
const g = document.getElementById('board');
const size = 30;
for (let row = 0; row < 8; row++) {
for (let col = 0; col < 8; col++) {
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect.setAttribute('x', col * size);
rect.setAttribute('y', row * size);
rect.setAttribute('width', size);
rect.setAttribute('height', size);
rect.setAttribute('fill', (row + col) % 2 === 0 ? '#1e293b' : '#f8fafc');
g.appendChild(rect);
}
}
</script>
</svg>

Разбор:

  • row и col — номера клетки (0…7), как координаты на доске.
  • col * size — x левого края; row * size — y верхнего края.
  • (row + col) % 2 === 0 — чёрные и белые клетки шахматным порядком (сумма чётная — тёмная).

Аналог в Turtle: шахматная сетка из точек — там dot, здесь квадраты.

Что изменить: size = 20 и цикл до 12 — доска 12×12; цвета #b45309 и #fef3c7 — «деревянная» доска.


4.2. Соты (шестиугольная сетка)

<svg width="320" height="280" viewBox="0 0 320 280">
<g id="hex" fill="#fde68a" stroke="#92400e" stroke-width="1"></g>
<script>
function hexPoints(cx, cy, r) {
return Array.from({length: 6}, (_, i) => {
const a = (Math.PI / 3) * i - Math.PI / 6;
return `${cx + r * Math.cos(a)},${cy + r * Math.sin(a)}`;
}).join(' ');
}
const g = document.getElementById('hex');
const r = 28;
const dx = r * 3;
const dy = r * Math.sqrt(3);
for (let row = 0; row < 4; row++) {
for (let col = 0; col < 5; col++) {
const cx = 40 + col * dx + (row % 2 ? dx / 2 : 0);
const cy = 40 + row * dy;
const poly = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
poly.setAttribute('points', hexPoints(cx, cy, r));
g.appendChild(poly);
}
}
</script>
</svg>

Разбор:

  • hexPoints — 6 вершин шестиугольника; - Math.PI / 6 — «плоская» грань сверху.
  • dx = r * 3 — горизонтальный шаг между центрами сот.
  • row % 2 ? dx / 2 : 0смещение каждого второго ряда (классическая ульевая сетка).

5. Фракталы

5.1. Дерево с рекурсией

Функция branch вызывает саму себя — как дерево в Turtle.

<svg width="400" height="400" viewBox="0 0 400 400">
<g transform="translate(200 360)" stroke="#78350f" stroke-width="2" fill="none" id="tree"></g>
<script>
const NS = 'http://www.w3.org/2000/svg';
const g = document.getElementById('tree');

function branch(x1, y1, len, angle, depth) {
if (depth <= 0 || len < 4) return;
const rad = (angle * Math.PI) / 180;
const x2 = x1 + len * Math.sin(rad);
const y2 = y1 - len * Math.cos(rad);
const line = document.createElementNS(NS, 'line');
line.setAttribute('x1', x1);
line.setAttribute('y1', y1);
line.setAttribute('x2', x2);
line.setAttribute('y2', y2);
g.appendChild(line);
branch(x2, y2, len * 0.72, angle - 28, depth - 1);
branch(x2, y2, len * 0.72, angle + 28, depth - 1);
}

branch(0, 0, 90, 0, 8);
</script>
</svg>

Разбор:

СтрокаСмысл
translate(200 360)«Корень» внизу по центру — дерево растёт вверх
if (depth <= 0) returnБаза рекурсии — без неё бесконечные ветки
y2 = y1 - len * Math.cos(rad)Минус перед cos — в SVG Y вниз, «вверх» это уменьшение y
len * 0.72Каждая следующая ветка короче — дерево сужается
angle ± 28Левая и правая ветви от текущей
depth - 1Счётчик глубины уменьшается на каждом уровне

Что изменить: depth 86 — проще и быстрее; 2835 — более «раскидистое» дерево.


5.2. Снежинка Коха

Рекурсивное замещение отрезка — классический фрактал для школьной олимпиады.

<svg width="320" height="320" viewBox="-160 -140 320 280">
<path id="koch" fill="none" stroke="#0284c7" stroke-width="2"/>
</svg>
<script>
function kochSegment(x1, y1, x2, y2, depth) {
if (depth === 0) return `M ${x1} ${y1} L ${x2} ${y2}`;
const dx = x2 - x1, dy = y2 - y1;
const ax = x1 + dx / 3, ay = y1 + dy / 3;
const bx = x1 + 2 * dx / 3, by = y1 + 2 * dy / 3;
const len = Math.hypot(dx, dy) / 3;
const ang = Math.atan2(dy, dx) - Math.PI / 2;
const px = ax + len * Math.cos(ang + Math.PI / 3);
const py = ay + len * Math.sin(ang + Math.PI / 3);
return [
kochSegment(x1, y1, ax, ay, depth - 1),
kochSegment(ax, ay, px, py, depth - 1),
kochSegment(px, py, bx, by, depth - 1),
kochSegment(bx, by, x2, y2, depth - 1),
].join(' ');
}

const h = 120;
const d = [
kochSegment(-h, 0, h, 0, 4),
kochSegment(h, 0, 0, -h * Math.sqrt(3) / 2, 4),
kochSegment(0, -h * Math.sqrt(3) / 2, -h, 0, 4),
].join(' ');
document.getElementById('koch').setAttribute('d', d);
</script>

Разбор:

  • depth === 0 — рисуем обычный отрезок M… L….
  • Иначе делим отрезок на три части и вставляем «горб» в середине (треугольник Коха).
  • Три вызова внизу — три стороны равностороннего треугольника → замкнутая снежинка.
  • depth 4 — уже детальная; 5 — тяжелее для слабого ПК.

6. Анимация

6.1. SMIL — вращение без JavaScript

<svg width="200" height="200" viewBox="0 0 200 200">
<rect x="70" y="70" width="60" height="60" fill="#6366f1">
<animateTransform attributeName="transform" type="rotate"
from="0 100 100" to="360 100 100" dur="4s" repeatCount="indefinite"/>
</rect>
</svg>

Разбор:

АтрибутСмысл
animateTransformВстроенная SVG-анимация (SMIL)
type="rotate"Вращение
from="0 100 100"Старт: 0° вокруг точки (100, 100)
to="360 100 100"Финиш: полный оборот
dur="4s"Один оборот за 4 секунды
repeatCount="indefinite"Бесконечно
SMIL и браузеры

SMIL-анимация работает в Firefox и Safari; в Chrome для SVG она отключена. Для сайта в продакшене используйте CSS-анимации. Для урока и быстрого эксперимента SMIL всё ещё нагляден.


6.2. CSS-анимация inline-SVG (работает в Chrome)

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>SVG + CSS</title>
<style>
body { margin: 0; display: grid; place-items: center; min-height: 100dvh; background: #0f172a; }
.pulse { animation: pulse 2s ease-in-out infinite; transform-origin: center; }
@keyframes pulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.15); opacity: 0.85; }
}
@media (prefers-reduced-motion: reduce) {
.pulse { animation: none; }
}
</style>
</head>
<body>
<svg width="200" height="200" viewBox="0 0 200 200" class="pulse" role="img" aria-label="Пульсирующий круг">
<circle cx="100" cy="100" r="60" fill="#22d3ee"/>
</svg>
</body>
</html>

Разбор:

  • class="pulse" на <svg> — CSS анимирует весь SVG как один блок.
  • transform-origin: center — масштаб от центра, а не от угла.
  • @keyframes pulse — 0% и 100% нормальный размер; 50% — чуть больше и прозрачнее.
  • prefers-reduced-motion — уважение настройки «уменьшить движение» в системе.

Что изменить: 2s0.8s — быстрее пульс; scale(1.15)1.3 — сильнее «дыхание».


7. Иконка и символ <use>

Один раз нарисовали звезду — используете много раз (спрайт иконок на сайте).

<svg width="0" height="0" style="position:absolute" aria-hidden="true">
<symbol id="icon-star" viewBox="0 0 24 24">
<polygon points="12,2 15,9 22,9 16,14 18,22 12,17 6,22 8,14 2,9 9,9"
fill="currentColor"/>
</symbol>
</svg>

<svg width="48" height="48" viewBox="0 0 24 24" style="color:#eab308" role="img" aria-label="Звезда">
<use href="#icon-star"/>
</svg>
<svg width="32" height="32" viewBox="0 0 24 24" style="color:#64748b" aria-hidden="true">
<use href="#icon-star"/>
</svg>

Разбор:

  • Первый SVG width="0" height="0"склад символов, на экране не занимает место.
  • <symbol id="icon-star"> — шаблон; viewBox задаёт систему координат иконки.
  • fill="currentColor" — цвет берётся из CSS color родителя.
  • <use href="#icon-star"/> — вставка копии символа; второй SVG задаёт размер 48×48.

8. Экспорт и использование

ЗадачаДействие
Иконка на сайтеСохранить icon.svg, подключить <img src="icon.svg" alt="…">
Стилизация CSSInline <svg> в HTML — классы на <circle>, <path>
Сжатие файлаSVGOMG — убирает лишние пробелы и точки
Визуальный редакторFigma, Inkscape — нарисовать, экспортировать SVG
PythonБиблиотека svgwrite — генерировать SVG из кода (аналог Turtle, но сразу в файл)

Turtle, p5.js и SVG — что выбрать

ИнструментГде рисуетеЛучше для
TurtleОкно Python на компьютереУрок информатики, первые циклы, ЕГЭ-стиль
p5.jsБраузер, CanvasАнимация, игры, творческий код
SVGБраузер, файл .svgИконки, логотипы, диаграммы, масштаб без потерь
CSS-анимацииHTML + CSSКнопки, появление блоков, UI-эффекты

SVG описывает форму, а не пиксели: один и тот же код подходит для favicon 16×16 и для баннера на 4K. На уроке часто идут параллельно: Turtle для логики циклов, SVG для результата в браузере и портфолио.


Типичные ошибки

СимптомПричинаРешение
Пустой квадратfill="none" и нет strokeДобавьте stroke="#000"
Фигура «уехала» за крайКоординаты вне viewBoxУвеличьте viewBox или сдвиньте x/y
Градиент не виденurl(#id) из другого SVG<defs> в том же <svg>
<use href="#id"> не работаетСтарый браузерВ HTML5 — href; в XML — xlink:href
Анимация не крутится в ChromeSMIL отключёнCSS @keyframesпример выше
JS не добавляет кругиНеверный namespacecreateElementNS('http://www.w3.org/2000/svg', …)

Что дальше


См. также

Другие статьи этого же раздела в боковом меню (как на странице "О разделе").