Базовые фигуры: rect, circle, ellipse, line, polyline, polygon

D3.js работает поверх DOM и SVG, позволяя напрямую связывать данные с графическими примитивами и управлять их атрибутами через декларативные цепочки вызовов. Базовые фигуры в D3.js строятся на SVG-элементах, где каждый графический объект представляет собой узел DOM с набором атрибутов, определяющих геометрию и визуальное поведение.

D3.js не вводит собственный графический движок. Вместо этого используется SVG (Scalable Vector Graphics), где каждая фигура описывается через XML-подобные теги. D3 лишь управляет созданием и модификацией этих тегов.

Ключевая особенность SVG:

  • координатная система с началом в левом верхнем углу
  • ось X направлена вправо
  • ось Y направлена вниз
  • масштабирование без потери качества

Создание SVG-контейнера:

const svg = d3.select("body")
  .append("svg")
  .attr("width", 600)
  .attr("height", 400);

Этот контейнер становится сценой, внутри которой размещаются все базовые фигуры.

Прямоугольник: rect

Прямоугольник является одной из наиболее часто используемых форм в визуализации: столбчатые диаграммы, контейнеры, блоки интерфейса.

Основные атрибуты:

  • x, y — позиция
  • width, height — размеры
  • rx, ry — скругление углов

Создание прямоугольника:

svg.append("rect")
  .attr("x", 50)
  .attr("y", 50)
  .attr("width", 120)
  .attr("height", 80)
  .attr("fill", "steelblue");

Прямоугольник часто связывается с данными через data():

const data = [30, 80, 45, 60];

svg.selectAll("rect")
  .data(data)
  .enter()
  .append("rect")
  .attr("x", (d, i) => i * 60)
  .attr("y", d => 200 - d)
  .attr("width", 40)
  .attr("height", d => d)
  .attr("fill", "orange");

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

Круг: circle

Круг определяется координатами центра и радиусом.

Атрибуты:

  • cx, cy — центр
  • r — радиус
svg.append("circle")
  .attr("cx", 150)
  .attr("cy", 100)
  .attr("r", 40)
  .attr("fill", "tomato");

При работе с данными круги часто используются в точечных диаграммах:

const points = [10, 40, 80, 120];

svg.selectAll("circle")
  .data(points)
  .enter()
  .append("circle")
  .attr("cx", d => d)
  .attr("cy", 150)
  .attr("r", 6);

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

Эллипс: ellipse

Эллипс расширяет круг, вводя отдельные радиусы по осям X и Y.

Атрибуты:

  • cx, cy — центр
  • rx — горизонтальный радиус
  • ry — вертикальный радиус
svg.append("ellipse")
  .attr("cx", 200)
  .attr("cy", 120)
  .attr("rx", 60)
  .attr("ry", 30)
  .attr("fill", "purple");

Эллипсы применяются для:

  • визуализации распределений
  • создания акцентов в диаграммах
  • имитации перспективы

Изменение соотношения rx и ry позволяет управлять «сжатием» формы по одной из осей.

Линия: line

Линия задаётся двумя точками: начальной и конечной.

Атрибуты:

  • x1, y1 — начало
  • x2, y2 — конец
svg.append("line")
  .attr("x1", 50)
  .attr("y1", 50)
  .attr("x2", 300)
  .attr("y2", 200)
  .attr("stroke", "black")
  .attr("stroke-width", 2);

Линии часто используются для:

  • построения сеток
  • соединения узлов графов
  • отображения трендов

В связке с данными:

const pairs = [
  { x1: 10, y1: 10, x2: 200, y2: 80 },
  { x1: 20, y1: 100, x2: 250, y2: 150 }
];

svg.selectAll("line")
  .data(pairs)
  .enter()
  .append("line")
  .attr("x1", d => d.x1)
  .attr("y1", d => d.y1)
  .attr("x2", d => d.x2)
  .attr("y2", d => d.y2)
  .attr("stroke", "gray");

Ломаная линия: polyline

Polyline представляет собой набор соединённых отрезков без замыкания фигуры.

Атрибут:

  • points — строка координат
svg.append("polyline")
  .attr("points", "10,10 60,40 120,20 180,80")
  .attr("fill", "none")
  .attr("stroke", "green");

В D3.js координаты часто формируются динамически:

const points = [
  [10, 10],
  [60, 40],
  [120, 20],
  [180, 80]
];

svg.append("polyline")
  .attr("points", points.map(p => p.join(",")).join(" "))
  .attr("fill", "none")
  .attr("stroke", "blue");

Polyline применяется для:

  • временных рядов
  • траекторий движения
  • упрощённых графиков без заливки

Замкнутый многоугольник: polygon

Polygon аналогичен polyline, но автоматически замыкает фигуру, соединяя последнюю точку с первой.

svg.append("polygon")
  .attr("points", "50,10 90,50 70,100 30,80")
  .attr("fill", "lightblue")
  .attr("stroke", "black");

С данными:

const shape = [
  [50, 10],
  [90, 50],
  [70, 100],
  [30, 80]
];

svg.append("polygon")
  .attr("points", shape.map(d => d.join(",")).join(" "))
  .attr("fill", "rgba(100, 150, 255, 0.5)");

Polygon используется для:

  • геометрических диаграмм
  • областей на картах
  • произвольных фигур в визуализациях

Связывание базовых фигур с данными

Основная сила D3.js заключается в механизме data binding. Каждый SVG-элемент может быть напрямую связан с элементом массива данных, что позволяет синхронизировать состояние визуализации и данных.

Типовой цикл:

  • selection
  • data binding
  • enter selection
  • append elements
  • установка атрибутов

Пример универсального подхода:

const dataset = [
  { type: "rect", x: 10, y: 10, w: 80, h: 40 },
  { type: "circle", cx: 200, cy: 60, r: 30 }
];

const elements = svg.selectAll("*")
  .data(dataset)
  .enter();

elements.append(d => d.type)
  .attr("x", d => d.x)
  .attr("y", d => d.y)
  .attr("width", d => d.w)
  .attr("height", d => d.h)
  .attr("cx", d => d.cx)
  .attr("cy", d => d.cy)
  .attr("r", d => d.r);

Такой подход демонстрирует гибкость SVG-рендеринга, где тип элемента может определяться динамически.

Стилизация базовых фигур

Все SVG-элементы поддерживают набор визуальных атрибутов:

  • fill — заливка
  • stroke — цвет обводки
  • stroke-width — толщина линии
  • opacity — прозрачность
svg.append("rect")
  .attr("x", 40)
  .attr("y", 40)
  .attr("width", 100)
  .attr("height", 60)
  .attr("fill", "#4a90e2")
  .attr("stroke", "#1f3a93")
  .attr("stroke-width", 3)
  .attr("opacity", 0.8);

Стили могут задаваться и через CSS-классы:

svg.append("circle")
  .attr("cx", 100)
  .attr("cy", 100)
  .attr("r", 25)
  .attr("class", "node");
.node {
  fill: #e74c3c;
  stroke: #2c3e50;
}

Координатная логика и преобразования

Базовые фигуры в D3.js часто комбинируются с трансформациями SVG:

  • translate
  • scale
  • rotate
svg.append("rect")
  .attr("x", 0)
  .attr("y", 0)
  .attr("width", 50)
  .attr("height", 50)
  .attr("transform", "translate(100,100) rotate(45)");

Трансформации позволяют:

  • группировать элементы
  • создавать сложные композиции
  • управлять визуальной иерархией без изменения исходных координат

Комбинирование фигур в композиции

Базовые примитивы часто используются совместно для построения сложных визуальных структур.

Пример композиции:

svg.append("rect")
  .attr("x", 50)
  .attr("y", 50)
  .attr("width", 200)
  .attr("height", 100)
  .attr("fill", "#ecf0f1");

svg.append("circle")
  .attr("cx", 150)
  .attr("cy", 100)
  .attr("r", 30)
  .attr("fill", "#3498db");

svg.append("line")
  .attr("x1", 50)
  .attr("y1", 50)
  .attr("x2", 250)
  .attr("y2", 150)
  .attr("stroke", "#2c3e50");

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