Nivo в своей базовой концепции опирается на декларативное описание графиков и разделение ответственности между вычислением геометрии данных и их отрисовкой. В этом контексте Canvas API выступает альтернативным рендер-слоем наряду с SVG и WebGL-подходами, обеспечивая оптимизацию производительности при работе с большими объёмами данных и высокой частотой обновлений.
Canvas API представляет собой растровую модель рисования, где итоговое изображение формируется непосредственно в bitmap-поверхности. В отличие от SVG, где каждый элемент графика существует как отдельный DOM-узел, Canvas не хранит структуру сцены после отрисовки, что существенно влияет на поведение библиотек визуализации.
В экосистеме Nivo SVG используется по умолчанию для большинства компонентов благодаря:
Canvas применяется в случаях, когда SVG становится узким местом.
Ключевые различия:
SVG-подход:
Canvas-подход:
ctx.draw...)В Nivo это приводит к архитектурному разделению: логика остаётся декларативной, а слой рендеринга становится заменяемым.
Canvas API работает на основе непосредственного контекста рисования
(CanvasRenderingContext2D), где каждая операция изменяет
пиксели буфера.
Каждый кадр требует полного или частичного пересчёта сцены:
clearRect)Это принципиально отличается от SVG, где браузер самостоятельно оптимизирует перерисовку узлов.
Canvas не хранит структуру объектов графика. В Nivo это означает:
Внутри Nivo Canvas используется как специализированный renderer, подключаемый к абстракциям chart components. Основная идея — отделение data-to-geometry слоя от geometry-to-pixels слоя.
Типичный поток данных:
context2dКлючевой аспект — сохранение React-ориентированной модели описания графика при отказе от DOM как основного инструмента визуализации.
Canvas становится критически важным при следующих условиях:
Причина заключается в стоимости DOM-операций в SVG:
Canvas ограничивает pipeline до одного этапа — rasterization.
В Canvas-реализации Nivo ключевым становится контроль над частотой рендеринга.
Типовые стратегии:
1. requestAnimationFrame Обеспечивает синхронизацию с refresh rate дисплея.
2. dirty checking Перерисовка только изменившихся слоёв сцены.
3. memoization геометрии Сохранение вычисленных координат:
const points = useMemo(() =>
data.map(d => ({
x: xScale(d.x),
y: yScale(d.y)
}))
, [data, xScale, yScale])
Canvas не имеет встроенной модели событий для отдельных элементов. В Nivo это решается через:
Пример логики hit-testing:
function isPointInside(mouseX, mouseY, point) {
const dx = mouseX - point.x
const dy = mouseY - point.y
return dx * dx + dy * dy < point.radius * point.radius
}
Это делает интерактивность более вычислительно затратной, но масштабируемой при правильной оптимизации.
Одной из ключевых особенностей Canvas является необходимость учитывать плотность пикселей дисплея.
В Nivo это приводит к обязательной адаптации canvas buffer:
Без этого возникают артефакты размытости на Retina-экранах.
Canvas в Nivo часто разделяется на несколько логических слоёв:
Это позволяет:
Анимации реализуются через ручное интерполирование значений:
performance.now()SVG-анимации часто опираются на CSS transitions или Framer Motion, тогда как Canvas требует полного контроля над каждым кадром.
Несмотря на производительность, Canvas имеет ряд ограничений:
Поэтому в Nivo Canvas чаще используется как специализированный режим, а не основной.
Архитектурно Nivo часто применяет смешанные модели:
Такой подход позволяет сохранить:
Разделение слоёв становится ключевым паттерном:
Любая визуализация в Canvas-режиме опирается на трансформацию данных через scale-функции:
Фактически каждый элемент сцены проходит функцию отображения:
screen_x = scale_x(data_x)
screen_y = scale_y(data_y)
Canvas лишь фиксирует результат этих вычислений в пиксельном буфере.
Nivo скрывает различия между Canvas и SVG на уровне API компонентов, сохраняя единый декларативный интерфейс.
Canvas API при этом выступает как низкоуровневый backend, обеспечивающий:
Разделение уровней позволяет поддерживать одинаковую модель данных при разных стратегиях визуализации, не нарушая общую архитектуру библиотеки.