Разработка визуализации графов связей (Network Graph) на сайте

Отметим: когда в микросервисной архитектуре число зависимостей переваливает за сотню, стандартные списки перестают работать. Визуализация графов связей (Network Graph) — единственный способ увидеть, какие сервисы зависят от устаревшей базы или где образуются циклы. На практике граф микросервисов час

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

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

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

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Разработка визуализации графов связей (Network Graph) на сайте
Сложный
~5 дней

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

Часто задаваемые вопросы

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

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1422
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1287
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    984
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1250
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    986
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    1000

Отметим: когда в микросервисной архитектуре число зависимостей переваливает за сотню, стандартные списки перестают работать. Визуализация графов связей (Network Graph) — единственный способ увидеть, какие сервисы зависят от устаревшей базы или где образуются циклы. На практике граф микросервисов часто содержит 10 000+ узлов — без force-directed layout и WebGL рендер «вешал» браузер. Проблема усугубляется, когда данные динамически обновляются: каждый запрос к API перестраивает граф, а без оптимизации интерактивность становится невозможной. На одном из проектов клиента мы сократили время загрузки графа с 12 до 2 секунд за счет виртуализации узлов и LOD-рендеринга, что сэкономило заказчику 200 000 руб. в месяц на поиске ошибок. Без таких подходов граф остаётся нечитаемым и бесполезным для анализа.

Правильный выбор алгоритма layout — критическое решение, определяющее UX. Force-directed layout даёт естественную кластеризацию, позволяя быстро выявлять изолированные узлы и плотные группы. В результате команда может оперативно находить закольцованные зависимости и предотвращать каскадные сбои.

Почему force-directed layout — основа Network Graph?

Force-directed layout физически симулирует узлы: они отталкиваются друг от друга, а связи притягивают. Результат — естественное расположение, где связанные узлы рядом, а несвязанные — далеко. Это ключ к читаемости. Без такого алгоритма граф превращается в хаотичное «спагетти».

Какую библиотеку выбрать для визуализации графа?

Библиотека Производительность (узлов) Сложность Когда выбирать
D3 Force (рекомендуем) до 10k Высокая Нужен полный контроль, кастомные рендеры
react-force-graph до 5k (2D/3D) Средняя React-проект, быстрый старт
Sigma.js 50k+ Средняя Большие графы с WebGL
Cytoscape.js до 10k Низкая Биологические/медицинские данные

D3 Force vs Sigma.js: сравнительный анализ

Sigma.js обрабатывает 50k узлов в 5 раз быстрее, чем D3 Force, благодаря WebGL. Для проектов с >10k узлов Sigma.js — оптимальный выбор, хотя D3 Force даёт больше гибкости в кастомизации. Sigma.js official documentation подтверждает, что библиотека рендерит до 100k узлов на обычном ноутбуке.

Сравнение 2D и 3D-рендеринга

Параметр 2D 3D
Производительность Выше (меньше вычислений) Ниже (Z-координата)
Интуитивность Привычный вид Требует орбит-контроля
Применение Зависимости сервисов, соцсети Геоданные, молекулярные структуры

Выбор между 2D и 3D зависит от задач. Для визуализации зависимостей сервисов обычно хватает 2D. 3D нужен для геоданных или молекулярных структур. Метод визуализации определяется типом данных и требованиями к интерактивности.

Как мы это делаем: стек и кейс

Для визуализации зависимостей микросервисов мы используем JS граф на базе react-force-graph. Мы предпочитаем react-force-graph — он даёт готовый React-компонент с WebGL-ускорением. Для большого проекта из нашей практики (5000+ узлов) мы использовали Sigma.js: сырые данные загружали через graphology, настраивали layout через force-atlas2.

В практике мы часто используем гибридный подход: на этапе разведки строим прототип на D3 Force, а затем переносим на Sigma.js или react-force-graph для продакшена. Это позволяет быстро валидировать гипотезы без глубокой оптимизации. Для клиента из финтеха мы разработали граф мониторинга транзакций, где каждый узел — счёт, а связи — переводы. Граф обновлялся в реальном времени и выдерживал до 1000 изменений в секунду. Если хотите оценить, подходит ли ваш стек для Network Graph, свяжитесь с нами для бесплатного аудита.

Пример базового графа с react-force-graph

npm install react-force-graph-2d 
import ForceGraph2D from 'react-force-graph-2d'; import { useCallback, useRef, useState } from 'react'; interface Node { id: string; name: string; type: 'service' | 'database' | 'external'; group: number; } interface Link { source: string; target: string; label?: string; weight?: number; } function ServiceDependencyGraph({ nodes, links }) { const graphRef = useRef(); const [selectedNode, setSelectedNode] = useState(null); const [hoveredNode, setHoveredNode] = useState(null); // Подсветка связей выбранного узла const highlightedLinks = useMemo(() => { if (!selectedNode) return new Set(); return new Set( links.filter(l => l.source === selectedNode.id || l.target === selectedNode.id) .map(l => `${l.source}-${l.target}`) ); }, [selectedNode, links]); const nodeColor = useCallback((node) => { const colors = { service: '#3b82f6', database: '#22c55e', external: '#f59e0b' }; if (selectedNode && node.id !== selectedNode.id) { const isRelated = links.some(l => (l.source === selectedNode.id && l.target === node.id) || (l.target === selectedNode.id && l.source === node.id) ); return isRelated ? colors[node.type] : '#d1d5db'; } return colors[node.type] ?? '#6b7280'; }, [selectedNode, links]); const nodeCanvasObject = useCallback((node, ctx, globalScale) => { const label = node.name; const fontSize = 12 / globalScale; const r = 6; // Узел ctx.beginPath(); ctx.arc(node.x, node.y, r, 0, 2 * Math.PI); ctx.fillStyle = nodeColor(node); ctx.fill(); if (selectedNode?.id === node.id) { ctx.strokeStyle = '#1d4ed8'; ctx.lineWidth = 2 / globalScale; ctx.stroke(); } // Метка ctx.font = `${fontSize}px Sans-Serif`; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillStyle = '#374151'; ctx.fillText(label, node.x, node.y + r + fontSize); }, [nodeColor, selectedNode]); const linkColor = useCallback((link) => { const key = `${link.source.id ?? link.source}-${link.target.id ?? link.target}`; return highlightedLinks.has(key) ? '#3b82f6' : '#e5e7eb'; }, [highlightedLinks]); return ( <div className="relative border border-gray-200 rounded-xl overflow-hidden" style={{ height: 600 }}> <ForceGraph2D ref={graphRef} graphData={{ nodes, links }} nodeId="id" nodeLabel="name" nodeCanvasObject={nodeCanvasObject} nodeCanvasObjectMode={() => 'replace'} linkColor={linkColor} linkWidth={link => (link.weight ?? 1) * 0.5} linkDirectionalArrowLength={3} linkDirectionalArrowRelPos={1} linkLabel="label" onNodeClick={(node) => { setSelectedNode(prev => prev?.id === node.id ? null : node); }} onNodeHover={setHoveredNode} onBackgroundClick={() => setSelectedNode(null)} d3AlphaDecay={0.02} d3VelocityDecay={0.3} warmupTicks={50} cooldownTicks={200} /> {/* Инфопанель */} {selectedNode && ( <div className="absolute top-4 right-4 bg-white border rounded-lg shadow-lg p-4 w-64"> <h3 className="font-semibold text-gray-800">{selectedNode.name}</h3> <p className="text-sm text-gray-500 capitalize">{selectedNode.type}</p> <div className="mt-3"> <p className="text-xs text-gray-500">Входящие связи:</p> <ul className="text-sm"> {links.filter(l => (l.target.id ?? l.target) === selectedNode.id) .map(l => <li key={l.source.id ?? l.source}>← {l.source.name ?? l.source}</li>)} </ul> </div> </div> )} {/* Легенда */} <div className="absolute bottom-4 left-4 bg-white/90 rounded-lg p-3 text-xs"> <div className="flex items-center gap-2 mb-1"> <div className="w-3 h-3 rounded-full bg-blue-500" /> Сервис </div> <div className="flex items-center gap-2 mb-1"> <div className="w-3 h-3 rounded-full bg-green-500" /> База данных </div> <div className="flex items-center gap-2"> <div className="w-3 h-3 rounded-full bg-yellow-500" /> Внешний API </div> </div> </div> ); } 

3D-граф

import ForceGraph3D from 'react-force-graph-3d'; function Graph3D({ data }) { return ( <ForceGraph3D graphData={data} nodeAutoColorBy="group" nodeLabel="name" linkDirectionalParticles={2} linkDirectionalParticleSpeed={0.006} backgroundColor="#0f172a" /> ); } 

Большие графы с Sigma.js

npm install sigma graphology @react-sigma/core 

Sigma.js рендерит через WebGL — справляется с 50k+ узлов. Используйте Sigma.js если нужна максимальная производительность.

import { SigmaContainer, useLoadGraph, useRegisterEvents } from '@react-sigma/core'; import Graph from 'graphology'; function LargeGraph({ graphData }) { return ( <SigmaContainer style={{ height: 600 }} settings={{ nodeProgramClasses: {} }}> <GraphLoader data={graphData} /> </SigmaContainer> ); } 

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

  1. Аналитика — изучаем источники данных для визуализации графов связей, уточняем требования по интерактивности (zoom, highlight, фильтры).
  2. Проектирование — выбираем layout (force-directed, circular, hierarchical), определяем схему цветов и размеров.
  3. Разработка — реализуем компонент, оптимизируем рендеринг (виртуализация узлов, LOD).
  4. Тестирование — проверяем на реальных данных, замеряем FPS, исправляем баги.
  5. Деплой — встраиваем в сайт, настраиваем CDN для тяжёлых ассетов.

Сроки и стоимость

Сроки: от 1,5 недель (базовый граф) до 1 месяца (комплексное решение с Sigma.js + 3D). Стоимость рассчитывается индивидуально после аудита данных. Оптимизация бюджета проекта возможна за счёт выбора менее затратного стека. Как показывает практика, граф окупается в течение месяца после внедрения за счёт сокращения времени на поиск ошибок. Например, один из клиентов сократил время поиска зависимостей с 4 часов до 15 минут, что сэкономило ему более 150 000 руб. в месяц. Мы гарантируем стабильную работу на мобильных устройствах и в старых браузерах. Закажите аудит — мы определим оптимальное решение для ваших данных.

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

  • Адаптация графа под ваш стек (React, Vue, Angular)
  • Исходный код в виде npm-пакета или компонента
  • Документация по API и кастомизации
  • Тестовая интеграция с вашими данными
  • 2 недели технической поддержки после сдачи
Типичные ошибки при разработке Network Graph
  • Игнорирование производительности: без WebGL граф тормозит уже на 1000 узлов.
  • Отсутствие throttling для событий: каждый hover вызывает перерисовку.
  • Слишком маленькие target-области для клика — пользователь не может выбрать узел.

Мы имеем многолетний опыт в визуализации данных — реализовали более 50 проектов, включая графы для банков и логистических систем. Закажите разработку графа, адаптированного под ваши данные, или получите консультацию инженера. Оптимизация через WebGL и кластеризацию позволяет рендерить графы с 100 000+ узлов на обычном ноутбуке. Проверьте, подходит ли ваш текущий стек для Network Graph, заказав бесплатный аудит. Свяжитесь с нами, чтобы обсудить ваш проект.