Позиционирование и смещение

В Nivo вся система визуализации строится вокруг строгой координатной модели SVG/Canvas, где каждый график имеет внутреннюю область отрисовки (inner area) и внешние отступы (margin). Позиционирование элементов определяется не абсолютными координатами страницы, а пересчётом данных в координаты графика через шкалы (scales).

Ключевая идея заключается в разделении пространства:

  • внешняя область (SVG контейнер целиком)
  • внутренняя область (chart area)
  • служебные зоны (оси, легенды, подписи)

Любое смещение элементов происходит относительно внутреннего прямоугольника, вычисляемого после применения margins.


Margin как основной механизм смещения

Margin задаёт внешний отступ графика и определяет, где начинается координатная сетка.

<ResponsiveLine
    data={data}
    margin={{ top: 50, right: 120, bottom: 60, left: 80 }}
/>

После применения margin:

  • область построения уменьшается
  • оси получают пространство для подписей
  • легенды и tooltips не перекрывают данные

Внутренние координаты пересчитываются как:

innerWidth = width - left - right
innerHeight = height - top - bottom

Любое визуальное смещение далее опирается именно на innerWidth и innerHeight.


Смещение осей и их позиционирование

Оси в Nivo (xAxis, yAxis) не являются фиксированными элементами DOM. Их положение вычисляется через конфигурацию scale и ориентацию.

<ResponsiveBar
    data={data}
    margin={{ top: 40, right: 40, bottom: 50, left: 60 }}
    axisBottom={{
        tickSize: 5,
        tickPadding: 8,
        tickRotation: 0
    }}
    axisLeft={{
        tickSize: 5,
        tickPadding: 8,
        tickRotation: 0
    }}
/>

Параметры влияния на смещение:

  • tickPadding — расстояние от оси до подписи
  • tickSize — длина делений
  • tickRotation — изменение геометрии подписи, влияющее на bounding box
  • legendOffset — дополнительное смещение легенды оси

Ось фактически «прижимается» к границе inner area, а подписи выходят за её пределы в сторону margin-зоны.


Легенды и управление их положением

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

legends={[
    {
        anchor: 'right',
        direction: 'column',
        translateX: 100,
        itemWidth: 80,
        itemHeight: 20,
        symbolSize: 12
    }
]}

Основные параметры смещения:

  • anchor — базовая точка привязки (left, right, top, bottom)
  • translateX / translateY — ручное смещение относительно anchor
  • direction — влияет на направление потока элементов
  • itemSpacing — расстояние между элементами списка

Легенда не участвует в layout flow, поэтому любые смещения должны компенсировать её потенциальное перекрытие с chart area вручную через margin.


Tooltip и динамическое смещение

Tooltip в Nivo позиционируется динамически на основе координат курсора. Основной принцип — следование за pointer с ограничением выхода за границы контейнера.

tooltip={({ point }) => (
    <div
        style={{
            transform: `translate(${point.x}px, ${point.y}px)`
        }}
    >
        {point.data.yFormatted}
    </div>
)}

Механика смещения:

  • базовая позиция берётся из координат data-point
  • добавляется offset для предотвращения перекрытия курсора
  • применяется clamp внутри SVG/HTML контейнера

Для кастомного контроля часто вводятся дополнительные сдвиги:

  • offsetX — горизонтальный сдвиг
  • offsetY — вертикальный сдвиг
  • boundary padding — защита от выхода за край

Grid и выравнивание в координатной сетке

Сетка строится на основе делений осей и inherits их смещения. Grid lines всегда выровнены с tick positions.

<ResponsiveLine
    enableGridX={true}
    enableGridY={true}
/>

Смещение сетки происходит косвенно:

  • изменение scale domain сдвигает все линии
  • изменение tickValues влияет на плотность сетки
  • padding в axis влияет на визуальное совпадение сетки с подписями

Grid не имеет собственного offset — он полностью зависит от осей.


Бар-чарты: внутренние смещения и spacing

В Nivo bar charts используют дополнительный слой смещения внутри категориальной шкалы.

<ResponsiveBar
    data={data}
    groupMode="grouped"
    padding={0.2}
    innerPadding={3}
/>

Факторы смещения:

  • padding — расстояние между группами баров
  • innerPadding — расстояние между элементами внутри группы
  • indexScale — определяет положение категории по оси
  • valueScale — масштабирует высоту/ширину

Фактически каждый бар вычисляется как:

x = scale(index) + offsetGroup + offsetBar

Любое изменение padding приводит к перераспределению всей структуры координат внутри inner area.


Radial charts и центрирование смещения

В радиальных диаграммах смещение выражается через центр (centerX, centerY) и радиус.

<ResponsivePie
    innerRadius={0.5}
    padAngle={0.7}
/>

Особенности позиционирования:

  • центр всегда вычисляется как середина innerWidth/innerHeight
  • margin смещает весь радиальный контейнер
  • legends часто требуют ручного translateX/translateY
  • padAngle влияет на визуальные зазоры между секторами

Смещение здесь не линейное, а угловое:

angle = startAngle + arcLength + padAngle

Layers и визуальное смещение в глубину

Система layers управляет порядком отрисовки, влияя на восприятие смещения элементов по глубине.

layers={[
    'grid',
    'axes',
    'bars',
    'markers',
    'legends'
]}

Изменение порядка слоёв:

  • не влияет на координаты
  • влияет на перекрытие элементов
  • может создавать визуальные «смещения» из-за z-order

Custom layer позволяет вводить дополнительные offset-эффекты, например тени или аннотации.


Аннотации и абсолютное смещение в пределах графика

Аннотации используют координаты данных, но отрисовываются с дополнительными transform-сдвигами.

annotations={[
    {
        type: 'circle',
        match: { index: 2 },
        noteX: 20,
        noteY: -30
    }
]}

Параметры смещения:

  • noteX / noteY — относительное смещение подписи
  • offsetX / offsetY — смещение маркера
  • position — привязка к точке (top, bottom, center)

Аннотации всегда рассчитываются после scale трансформации данных.


Сводная модель смещения в Nivo

Внутренняя модель позиционирования включает последовательные этапы:

  1. вычисление размеров контейнера
  2. вычитание margin → inner area
  3. применение scales (x/y/angle/radius)
  4. распределение элементов (bars, points, arcs)
  5. наложение axes и legends
  6. финальные offset корректировки (tooltip, annotations)

Любое визуальное смещение является результатом комбинации этих слоёв, а не отдельной координатной правки.