Разработка кастомных визуализаций данных на Visx (D3 + React)

Стандартные библиотеки графиков часто не справляются с нестандартными задачами: ограничивают кастомизацию или тормозят на больших данных. Мы разрабатываем кастомные визуализации на Visx, объединяя гибкость D3 и мощность React для создания интерактивных диаграмм любой сложности. Наша команда реализует проект под ключ — от концепции до внедрения и последующей поддержки, обеспечивая плавную работу даже с крупными датасетами.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Разработка кастомных визуализаций данных на Visx (D3 + React)
Средний
~3-5 дней
Часто задаваемые вопросы

Когда нужна кастомная визуализация на Visx?

Типовой запрос от клиента: отобразить динамику курса акций за последний год с возможностью приближения и тултипами. Recharts не справляется с нестандартной анимацией, Chart.js тормозит на 50 000 точках. Нужна кастомная визуализация на Visx — библиотеке Airbnb, объединяющей гибкость D3 с парадигмой React. Visx позволяет строить любые SVG-графики с полным контролем и высокой производительностью. Мы используем его в проектах с датасетами до 100 000 записей, обеспечивая плавную анимацию и мгновенное обновление.

Какие проблемы решает Visx?

Ограниченная кастомизация готовых библиотек

Recharts предлагает множество конфигураций, но любое отклонение от шаблона превращается в хак с переопределением пропсов. Visx дает полный контроль над SVG: вы управляете каждым элементом, шкалами и переходами.

Производительность на больших объёмах данных

D3-рендеринг через React-жизненный цикл может вызывать лишние ререндеры. Visx оптимизирует это за счет чистых компонентов и мемоизации. На практике мы добиваемся 60 FPS на датасетах из 10 000 точек.

Интеграция с React-приложением

Visx-компоненты — это обычные React-компоненты, которые легко встраиваются в любую архитектуру: Next.js, CRA, Vite. Не нужно подключать отдельный рендерер или контекст.

Как Visx решает задачу кастомизации?

Visx предлагает низкоуровневые примитивы: scaleTime, scaleLinear, LinePath, AreaClosed, AxisLeft, AxisBottom. Из них собирается любой график без оглядки на шаблоны. Для интерактива — хук useTooltip и события мыши. Весь код — TypeScript с типизацией данных.

Возьмем типовую задачу: линейный график с тултипом и зоной заливки. Пример реализации на Visx (фрагмент):

import { scaleTime, scaleLinear } from '@visx/scale';
import { LinePath, AreaClosed } from '@visx/shape';
import { AxisLeft, AxisBottom } from '@visx/axis';
import { GridRows, GridColumns } from '@visx/grid';
import { useTooltip, TooltipWithBounds, defaultStyles } from '@visx/tooltip';
import { localPoint } from '@visx/event';
import { bisector } from 'd3-array';
import { curveMonotoneX } from 'd3-shape';

interface DataPoint {
  date: Date;
  value: number;
}

const bisectDate = bisector<DataPoint, Date>(d => d.date).left;

function CustomLineChart({
  data,
  width,
  height,
  margin = { top: 20, right: 20, bottom: 40, left: 60 }
}: {
  data: DataPoint[];
  width: number;
  height: number;
  margin?: { top: number; right: number; bottom: number; left: number };
}) {
  const innerWidth = width - margin.left - margin.right;
  const innerHeight = height - margin.top - margin.bottom;

  const xScale = scaleTime({
    range: [0, innerWidth],
    domain: [
      Math.min(...data.map(d => d.date.getTime())),
      Math.max(...data.map(d => d.date.getTime()))
    ]
  });

  const yScale = scaleLinear({
    range: [innerHeight, 0],
    domain: [0, Math.max(...data.map(d => d.value)) * 1.1],
    nice: true
  });

  const { tooltipData, tooltipLeft, tooltipTop, showTooltip, hideTooltip } = useTooltip<DataPoint>();

  const handleTooltip = (event: React.MouseEvent<SVGRectElement>) => {
    const { x } = localPoint(event) || { x: 0 };
    const x0 = xScale.invert(x - margin.left);
    const index = bisectDate(data, x0, 1);
    const d0 = data[index - 1];
    const d1 = data[index];
    const d = !d1 || Math.abs(x0.getTime() - d0.date.getTime()) < Math.abs(x0.getTime() - d1.date.getTime()) ? d0 : d1;
    showTooltip({
      tooltipData: d,
      tooltipLeft: xScale(d.date) + margin.left,
      tooltipTop: yScale(d.value) + margin.top
    });
  };

  return (
    <div style={{ position: 'relative' }}>
      <svg width={width} height={height}>
        <g transform={`translate(${margin.left}, ${margin.top})`}>
          <GridRows scale={yScale} width={innerWidth} stroke="#f0f0f0" />
          <GridColumns scale={xScale} height={innerHeight} stroke="#f0f0f0" />
          <defs>
            <linearGradient id="areaGradient" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0%" stopColor="#3b82f6" stopOpacity={0.3} />
              <stop offset="100%" stopColor="#3b82f6" stopOpacity={0} />
            </linearGradient>
          </defs>
          <AreaClosed
            data={data}
            x={d => xScale(d.date)}
            y={d => yScale(d.value)}
            yScale={yScale}
            fill="url(#areaGradient)"
            curve={curveMonotoneX}
          />
          <LinePath
            data={data}
            x={d => xScale(d.date)}
            y={d => yScale(d.value)}
            stroke="#3b82f6"
            strokeWidth={2}
            curve={curveMonotoneX}
          />
          <AxisLeft scale={yScale} tickFormat={v => `${(v as number / 1000).toFixed(0)}k`} />
          <AxisBottom top={innerHeight} scale={xScale} tickFormat={d => format(d as Date, 'dd MMM')} />
          <rect
            width={innerWidth}
            height={innerHeight}
            fill="transparent"
            onMouseMove={handleTooltip}
            onMouseLeave={hideTooltip}
          />
          {tooltipData && (
            <g>
              <line
                x1={tooltipLeft! - margin.left}
                x2={tooltipLeft! - margin.left}
                y1={0}
                y2={innerHeight}
                stroke="#3b82f6"
                strokeDasharray="4,4"
                strokeWidth={1}
              />
              <circle
                cx={tooltipLeft! - margin.left}
                cy={tooltipTop! - margin.top}
                r={5}
                fill="#3b82f6"
                stroke="white"
                strokeWidth={2}
              />
            </g>
          )}
        </g>
      </svg>
      {tooltipData && (
        <TooltipWithBounds
          top={tooltipTop}
          left={tooltipLeft}
          style={{ ...defaultStyles, background: '#1e293b', color: 'white' }}
        >
          <div>
            <strong>{format(tooltipData.date, 'dd.MM.yyyy')}</strong>
            <br />
            {tooltipData.value.toLocaleString('ru')} $
          </div>
        </TooltipWithBounds>
      )}
    </div>
  );
}

ParentSize для адаптивности

import { ParentSize } from '@visx/responsive';

function ResponsiveChart({ data }) {
  return (
    <ParentSize>
      {({ width, height }) => (
        <CustomLineChart data={data} width={width} height={height || 300} />
      )}
    </ParentSize>
  );
}

Почему Visx, а не Chart.js?

Visx лучше Chart.js в ситуациях, где требуется нестандартная форма графика или сложные интерактивные сценарии. Chart.js проще в настройке и быстрее для простых диаграмм, но его архитектура хуже масштабируется под кастомные задачи. Visx дает полный доступ к SVG, что позволяет реализовать любую визуализацию. Наши клиенты экономят до 40% времени на разработке сложных дашбордов за счет использования Visx.

Сравнение Visx и Recharts

Критерий Visx Recharts
Уровень контроля Полный (SVG-примитивы) Средний (конфигурация пропсов)
Кастомизация Безграничная Ограничена шаблонами
Производительность Высокая (ручное управление) Средняя (автоматические ререндеры)
Время разработки 3-5 дней на тип 1-2 дня на тип
Порог входа Средний (нужно знать d3) Низкий (React-only)

Типичные ошибки при работе с Visx

  • Пропуск мемоизации шкал. Шкалы нужно создавать внутри useMemo или вне компонента, иначе каждый ререндер будет пересоздавать их, что ведёт к потере производительности.
  • Игнорирование ParentSize. Без адаптивного контейнера график не будет реагировать на изменение размеров окна, что ломает UX на мобильных устройствах.
  • Некорректная обработка краёв данных. Если данные содержат NaN или null, Visx может выбросить ошибку. Всегда фильтруйте данные перед передачей в компоненты.
  • Забыли про accessibility. SVG-графика должна быть доступна для скринридеров: добавляйте role="img" и aria-label.

Как создать кастомный график с нуля?

  1. Определите шкалы — scaleTime для времени, scaleLinear для значений.
  2. Опишите геометрию — LinePath для линии, AreaClosed для заливки.
  3. Добавьте оси — AxisLeft и AxisBottom.
  4. Реализуйте тултип — используйте хук useTooltip и события мыши.
  5. Оберните в адаптивный контейнер — ParentSize для автоматического ресайза.

Процесс работы и сроки

Этап Длительность
Аналитика и сбор требований 0.5–1 день
Прототипирование MVP 1–2 дня
Разработка финальной версии 3–5 дней на тип
QA и оптимизация производительности 1–2 дня
Деплой и интеграция 0.5–1 день

Полный цикл разработки одного типа визуализации занимает от 3 до 5 дней. Комплект из 3–4 различных типов — от 1.5 до 2 недель. Стоимость работ рассчитывается индивидуально и зависит от сложности интерактива и объёма данных.

Что входит в работу?

Мы выполняем разработку визуализации данных на Visx под ключ:

  • анализ требований и проектирование макета;
  • написание кода с нуля на React + TypeScript;
  • тестирование на реальных данных (до 100 000 записей);
  • адаптация под мобильные экраны и retina-дисплеи;
  • документация в README и инлайн-комментариях;
  • передача доступов к репозиторию и деплою;
  • обучение вашей команды работе с Visx (вебинар 1 час).

Свяжитесь с нами для обсуждения вашей задачи. Получите консультацию по кастомной визуализации.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1393
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1368
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1139
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1060