Skip to content

Конфигурация ​

Чарт полностью описывается одним объектом ChartOptions — он сериализуем, типобезопасен и одинаково работает в Charts.create и chart.update.

Минимальный рабочий пример:

ts
import { Charts } from 'grafit-charts';

const chart = Charts.create({
  container: document.getElementById('app')!, // куда рендерить
  data: [
    { month: 'Янв', plan: 120, fact: 134 },
    { month: 'Фев', plan: 125, fact: 118 },
  ],
  series: [
    { type: 'bar', xField: 'month', yField: 'plan', name: 'План' },
    { type: 'line', xField: 'month', yField: 'fact', name: 'Факт' },
  ],
});

Этого достаточно: оси, легенда, тултипы, подсветка и анимация входа включены по умолчанию.

Данные и серии ​

data — массив плоских объектов. Серии не содержат данных — они ссылаются на поля через xField/yField (у специализированных серий свои поля: angleField, sizeField, openField…).

series — discriminated union по полю type: после type: 'bar' TypeScript подсказывает только опции бара и не даст передать чужие. Все 27 типов серий перечислены в разделе «Серии», их общие опции — на странице Общие опции серий.

Оси ​

Если axes не заданы, виджет создаёт их сам: category снизу + number слева (для горизонтальных баров — наоборот; scatter/histogram просят числовую X-ось; heatmap — категориальные без линий и сетки). Явный блок axes нужен, когда требуется второй тип оси, формат подписей, crossLines и т.п. — см. Оси.

ts
axes: [
  { type: 'time', position: 'bottom', label: { format: '%d %b' } },
  { type: 'number', position: 'left', nice: true },
],

Вторая ось значений на противоположной стороне получает свою шкалу; keys на каждой оси говорит, какие серии она несёт — см. Две оси значений.

У полярного графика — радар, роза, радиальные столбцы — осей не список, а две, поэтому axes он читает парой: angle — категории по ободу, radius — кольца значений.

ts
axes: {
  angle: { title: { text: 'Месяц' } },
  radius: { min: 0, max: 60, ringCount: 3 },
},

См. Полярные оси.

Размер ​

Без width/height чарт следует за контейнером через ResizeObserver — задайте контейнеру размеры CSS-ом. Числа width/height фиксируют размер.

ОпцияТипПо умолчаниюОписание
widthnumberширина контейнерафиксированная ширина, px
heightnumberвысота контейнерафиксированная высота, px
minWidthnumber300нижняя граница измеренной ширины; 0 — без границы
minHeightnumber200нижняя граница измеренной высоты; 0 — без границы
responsivebooleantrue, если не заданы оба width и heightследовать ли за контейнером

У размера, измеренного по контейнеру, есть пол — 300×200: чарт в контейнере, которому ещё не задали размер, не выходит нечитаемо мелким. Пол именно пол, а не ограничение на контейнер: контейнер шире пола выигрывает, уже — нет, и тогда канвас оказывается внутри контейнера размером больше самого контейнера.

minWidth/minHeight двигают этот пол, 0 — убирает: плотной раскладке нужно именно это — плитка дашборда шириной 195 px, ряд KPI-карточек высотой 140 px, спарклайн в ячейке таблицы. Содержимое чарт подгоняет под ту площадь, что у него есть; лишнее убирается штатными опциями — legend.enabled, title, axes[].label.

ts
Charts.create({ container, data, series, minWidth: 0, minHeight: 0 });

Без пола контейнер может не измеряться вовсе — display: none, ещё не открытая вкладка. Чарт говорит об этом один раз в консоль и ждёт: раскладка на 0×0 не строится, а первый размер, который принесёт ResizeObserver, и станет тем, в котором чарт нарисуется. Уже нарисованный чарт, который спрятали, сохраняет раскладку, к которой вернётся.

responsive разделяет два вопроса, на которые раньше разом отвечали width/height: каким быть размеру и кто его считает. responsive: false меряет контейнер один раз и больше не возвращается к этому. responsive: true вместе с width/height оставляет наблюдатель за контейнером, а числа понижает до стартового размера — он берётся, только пока контейнеру нечего измерять.

Заголовки, поля, фон ​

ОпцияТипПо умолчаниюОписание
title.textstring—заголовок чарта
title.textAlign'left' | 'center' | 'right''center'горизонтальное выравнивание
title.fontSizePixels17размер шрифта заголовка
title.colorColorValueforegroundцвет
title.position'top' | 'bottom''top'над или под областью построения
title.paddingPaddingValue8 под заголовкомотступы вокруг текста заголовка; по умолчанию только со стороны графика
title.wrapbooleantrueпереносить длинный текст на несколько строк
subtitle.textstring—подзаголовок (приглушённый, те же опции)
subtitle.paddingPaddingValue8 под подзаголовкомотступы вокруг текста подзаголовка
paddingPaddingValue{ top: 12, right: 20, bottom: 12, left: 20 }внешние поля чарта: 12, [12, 20], [12, 20, 12, 20] или { top, right, bottom, left }
background.fillColorValueфон темызаливка подложки
background.visiblebooleantrueрисовать ли фон

Все опции заголовков с живыми примерами: Заголовок и подзаголовок.

Оверлеи и загрузка ​

ОпцияТипПо умолчаниюОписание
loadingbooleanfalseпоказать оверлей «Загрузка данных…»
overlays.loading.textstringиз localeтекст оверлея загрузки
overlays.noData.textstringиз localeтекст при пустых data
overlays.error.textstringиз localeтекст, когда рисовать нечего

Серия, которой достались шкалы, на которых её знаки не построить — столбцы против оси значений из категорий, ось time со значениями, которые не разбираются в даты, — не рисуется, но и не роняет чарт: остальное рисуется как обычно, причина один раз печатается в консоль, а оверлей error появляется, только если не нарисовалось вообще ничего. Рендер вызывается из тика анимации и из ResizeObserver, где исключение стало бы unhandled-ошибкой на каждом кадре, — поэтому он не бросает.

Конвенции ​

  • *Field / *Name — пары «ключ данных / отображаемое имя»: *Field указывает на поле в data, *Name показывается в легенде и тултипе.
  • { enabled } — каждый опциональный блок (legend, tooltip, axis.label, series.marker, …) включается/выключается этим флагом; блок без enabled: false включён.
  • format / formatter — формат значений строкой (',.2f', '.0%', '%d %b') или функцией; функции — изолированные листья, остальной объект сериализуем в JSON.
  • Мутации переданного объекта не отслеживаются — обновляйте чарт методами.

Обновление и методы инстанса ​

ts
await chart.updateDelta({ theme: 'dark' }); // точечное изменение
await chart.update(buildOptions(newData)); // полная замена
МетодОписание
update(options)полная замена options; Promise резолвится после рендера
updateDelta(patch)глубокий merge: объекты сливаются, массивы заменяются целиком
getOptions()текущие options
getState() / setState(state)зум и скрытые серии — см. Состояние
waitForUpdate()дождаться рендера (и догрузки веб-шрифтов)
showTooltip / clickNode / setSelection / zoomTo / …управление взаимодействиями из кода — см. Программное управление
getImageDataURL(opts?)PNG/JPEG как data-URL
download(opts?)скачать изображение ({ fileName?, fileFormat? })
destroy()освободить DOM и подписки

Все корневые блоки ​

БлокЧто делаетПодробнее
container, data, series, axesоснова чартавыше на этой странице
width, heightфиксированный размерРазмер
title, subtitleзаголовкиЗаголовки
padding, backgroundполя и фонЗаголовки
loading, overlaysоверлеиОверлеи
themeимя темы или объектТемы
fontsперерисовка после загрузки шрифтаТемы
legendлегендаЛегенда
gradientLegendцветовая шкала colorField-серийHeatmap
tooltipтултипы (режимы, позиция, захват)Тултип
highlightподсветка и приглушение при ховереТултип
crosshairперекрестиеCrosshair
zoom, navigatorзум и полоса диапазонаZoom
syncсинхронизация нескольких чартовСостояние
selectionвыбор данныхВыделение данных
listenersсобытия чартаСобытия
annotationsлинии/диапазоны/текст на чартеАннотации
animationвход и обновленияСостояние
initialStateстартовый зум/скрытые серииСостояние
contextMenuменю по правому кликуСостояние
localeстроки UIДоступность