Замкнутые формы в SVG-построениях D3.js строятся через генераторы
путей, которые формируют непрерывные или сегментированные
последовательности координат и преобразуют их в строку d
для элемента <path>. Ключевым отличием замкнутых форм
от линейных графиков является необходимость соединения последней точки с
первой, а также корректная обработка разрывов данных при сохранении
целостности геометрии.
В D3.js замкнутые формы чаще всего реализуются через:
d3.line()d3.area()d3.polygon* (на уровне вычислений)curveClosed-модификаторыЗамыкание формы в SVG означает добавление команды Z в
path, которая соединяет последнюю точку с первой, образуя контур без
разрывов.
const line = d3.line()
.x(d => d.x)
.y(d => d.y)
.curve(d3.curveLinearClosed);
Использование curveLinearClosed автоматически замыкает
контур, исключая необходимость ручного добавления первой точки в конец
массива.
Открытые линии:
d3.line()
Замкнутые линии:
d3.line()
.curve(d3.curveLinearClosed)
В открытых формах последний сегмент остаётся свободным, тогда как в замкнутых создаётся цикл. Это особенно важно при построении:
Метод defined() определяет, какие точки считаются
валидными для построения линии. Он применяется ко всем генераторам,
поддерживающим обработку разрывов: line, area,
radialLine.
const line = d3.line()
.x(d => d.x)
.y(d => d.y)
.defined(d => d.value !== null);
При встрече с undefined или null значением
линия разрывается, создавая отдельные сегменты path.
Алгоритм обработки данных внутри генератора:
defined()Это критично для временных рядов с пропусками данных.
При использовании замкнутых кривых возникает конфликт между:
const line = d3.line()
.defined(d => d.y != null)
.curve(d3.curveLinearClosed);
Если данные содержат пропуски, замыкание применяется отдельно к каждому непрерывному сегменту. Это означает, что:
Для областей (d3.area) defined() управляет
разрывами верхней и нижней границ одновременно.
const area = d3.area()
.x(d => d.x)
.y0(d => d.y0)
.y1(d => d.y1)
.defined(d => d.y1 != null);
При разрыве:
Замкнутые области с curveClosed создают замкнутые
полигоны, но только внутри валидных сегментов данных.
d3.curveLinearClosed добавляет финальное соединение
между последней и первой точкой без модификации входного массива
данных.
Особенности:
defined() напрямуюconst shape = d3.line()
.curve(d3.curveLinearClosed)
.defined(d => !isNaN(d.value));
const closedData = [...data, data[0]];
Используется, когда требуется полный контроль над формой и вычислениями.
d3.line().curve(d3.curveBasisClosed);
Используется для сглаженных замкнутых контуров.
При использовании кривых (curveBasis,
curveCardinal, curveCatmullRom) разрывы данных
приводят к:
Замкнутые версии кривых:
curveBasisClosedcurveCardinalClosedигнорируют глобальную непрерывность, заменяя её локальными циклами.
Комбинированное поведение можно описать следующим образом:
defined() делит входной массив на группы валидных
точекЭто приводит к формированию нескольких <path>
внутри одного генератора строкой d, если используется
split-рендеринг, либо одного path с несколькими subpath
(M ... Z M ... Z).
Внутренняя логика генератора можно представить так:
data → defined filter → сегменты → интерполяция → curve → замыкание → SVG path
Ключевым элементом является момент разбиения данных до применения замкнутой кривой.
ZПри использовании шкал (d3.scaleLinear,
d3.scaleTime) defined() не влияет на
преобразование координат, но влияет на:
Замкнутые формы изменяют топологию графика:
fill-ruleДля замкнутых форм:
fill активирует внутреннюю областьstroke обводит замкнутый контурdefined() напрямую влияет на сегментацию заливки, так
как SVG интерпретирует каждый subpath как отдельный контур.
При наличии шумов, пропусков и выбросов:
defined() выступает фильтром геометрической
целостностиВ результате формируется структура, где каждый непрерывный участок данных становится самостоятельной замкнутой геометрической сущностью внутри SVG path.