Розробка Treemap-діаграм для візуалізації ієрархій

Уявіть: у вас дашборд з бюджетом компанії на 500+ статей витрат. Ви витрачаєте 20 хвилин на пошук, де «діра». Наша діаграма treemap показує це за 2 секунди. Treemap робить одну річ добре: показує співвідношення частин в ієрархічній структурі. Площа прямокутника пропорційна значенню, колір — додатков

Розробка та обслуговування будь-яких видів сайтів:

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

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Розробка Treemap-діаграм для візуалізації ієрархій
Середній
від 1 дня до 3 днів

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

Часті запитання

Останні роботи

  • 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

Уявіть: у вас дашборд з бюджетом компанії на 500+ статей витрат. Ви витрачаєте 20 хвилин на пошук, де «діра». Наша діаграма treemap показує це за 2 секунди. Treemap робить одну річ добре: показує співвідношення частин в ієрархічній структурі. Площа прямокутника пропорційна значенню, колір — додатковий вимір: зростання/падіння, категорія, статус. Treemap — потужний інструмент для візуалізації ієрархій та співвідношень. Treemap читается в 10 раз быстрее таблицы. Восприятие площади в 5 раз быстрее, чем чтение числа. Якщо потрібно зрозуміти, що займає найбільше місця в бюджеті, дереві категорій, файловій системі чи портфелі активів, — treemap читається швидше за будь-яку таблицю. При цьому розробка treemap на React 18 і D3.js v7 дає повний контроль над кожним пікселем: кастомний tooltip, анімація при drill-down, адаптивна верстка під будь-яке розширення. Навіть на 10 000 вузлах layout будується за десятки мілісекунд — достатньо для real-time оновлень. Вартість базового treemap починається від $500. Повноцінна розробка під ключ — від $1200. Використання treemap дозволяє зекономити до 20 годин на місяць на аналізі даних, що при середній зарплаті аналітика $50/год дає економію $1000. Середня вартість проекту — $800, а економія від використання — до $1000 на місяць.

Завдання, які вирішує діаграма treemap

Погана читабельність таблиць з ієрархією. Коли в таблиці 10 000 рядків, знайти топ-5 категорій можна лише скролом і сортуванням. Treemap показує їх візуально — мозок обробляє площу миттєво.

Складність сприйняття пропорцій. У таблиці числа, але щоб зрозуміти, наскільки бюджет маркетингу більший за бюджет розробки, потрібно ділити. Treemap дає відповідь без обчислень.

Необхідність порівнювати частки в реальному часі. При оновленні даних (наприклад, котирування акцій) treemap з кольоровим кодуванням treemap показує, які активи зростають, а які падають. Достатньо одного погляду.

Реалізація treemap на React і D3.js

Ми використовуємо React 18 і D3.js v7. D3 — це не бібліотека діаграм, а швейцарський ніж для роботи з даними та SVG. Бібліотека D3.js надає потужний d3 treemap layout. Ми не використовуємо high-level обгортки, тому що кожен проект потребує кастомних рішень: особливий tooltip, анімація при drill-down, адаптивна верстка.

Ось типова реалізація інтерактивного treemap:

import { useEffect, useRef } from 'react'; import * as d3 from 'd3'; interface TreeNode { name: string; value?: number; children?: TreeNode[]; change?: number; } interface TreemapProps { data: TreeNode; width?: number; height?: number; colorBy?: 'category' | 'change'; } export function Treemap({ data, width = 800, height = 500, colorBy = 'category' }: TreemapProps) { const svgRef = useRef<SVGSVGElement>(null); useEffect(() => { if (!svgRef.current) return; const svg = d3.select(svgRef.current); svg.selectAll('*').remove(); const root = d3.hierarchy(data) .sum(d => d.value ?? 0) .sort((a, b) => (b.value ?? 0) - (a.value ?? 0)); d3.treemap() .size([width, height]) .paddingOuter(3) .paddingInner(2) .paddingTop(18) .round(true)(root); const colorScale = colorBy === 'change' ? d3.scaleDiverging(d3.interpolateRdYlGn).domain([-30, 0, 30]) : d3.scaleOrdinal(d3.schemeTableau10); const tooltip = d3.select('body').append('div') .style('position', 'absolute') .style('display', 'none') .style('background', 'rgba(15,23,42,0.9)') .style('color', '#f1f5f9') .style('padding', '8px 12px') .style('border-radius', '4px') .style('font-size', '13px') .style('pointer-events', 'none') .style('max-width', '220px'); const leaves = root.leaves(); const ancestors = root.descendants().filter(d => d.depth === 1); svg.selectAll('.group-rect') .data(ancestors) .join('rect') .attr('class', 'group-rect') .attr('x', (d: any) => d.x0) .attr('y', (d: any) => d.y0) .attr('width', (d: any) => d.x1 - d.x0) .attr('height', (d: any) => d.y1 - d.y0) .attr('fill', (d: any) => colorBy === 'change' ? '#e2e8f0' : d3.color(colorScale(d.data.name))!.brighter(0.7).toString()) .attr('stroke', '#fff') .attr('stroke-width', 2); svg.selectAll('.group-label') .data(ancestors) .join('text') .attr('class', 'group-label') .attr('x', (d: any) => d.x0 + 6) .attr('y', (d: any) => d.y0 + 13) .attr('font-size', 11) .attr('font-weight', '600') .attr('fill', '#374151') .text((d: any) => d.data.name); const cell = svg.selectAll('.cell') .data(leaves) .join('g') .attr('class', 'cell') .attr('transform', (d: any) => `translate(${d.x0},${d.y0})`); cell.append('rect') .attr('width', (d: any) => d.x1 - d.x0) .attr('height', (d: any) => d.y1 - d.y0) .attr('fill', (d: any) => { if (colorBy === 'change') return colorScale(d.data.change ?? 0); return colorScale((d.parent?.data.name ?? '') as string); }) .attr('fill-opacity', 0.85) .attr('stroke', '#fff') .attr('stroke-width', 1) .on('mouseover', (event, d: any) => { d3.select(event.currentTarget).attr('fill-opacity', 1); const pct = d.data.change != null ? `<br/>Зміна: ${d.data.change > 0 ? '+' : ''}${d.data.change.toFixed(1)}%` : ''; tooltip .style('display', 'block') .style('left', `${event.pageX + 12}px`) .style('top', `${event.pageY - 28}px`) .html(`<strong>${d.data.name}</strong><br/>${d3.format(',.0f')(d.value ?? 0)}${pct}`); }) .on('mouseout', (event) => { d3.select(event.currentTarget).attr('fill-opacity', 0.85); tooltip.style('display', 'none'); }); cell.append('text') .attr('x', 4) .attr('y', 14) .attr('font-size', 11) .attr('fill', '#fff') .attr('font-weight', '500') .text((d: any) => { const w = d.x1 - d.x0; const h = d.y1 - d.y0; return w > 40 && h > 20 ? d.data.name : ''; }) .each(function(d: any) { const el = d3.select(this); const maxWidth = d.x1 - d.x0 - 8; let text = d.data.name; while (this.getComputedTextLength() > maxWidth && text.length > 3) { text = text.slice(0, -1); el.text(text + '…'); } }); cell.append('text') .attr('x', 4) .attr('y', 26) .attr('font-size', 10) .attr('fill', 'rgba(255,255,255,0.8)') .text((d: any) => { const w = d.x1 - d.x0; const h = d.y1 - d.y0; return w > 50 && h > 35 ? d3.format(',.0f')(d.value ?? 0) : ''; }); return () => { tooltip.remove(); }; }, [data, width, height, colorBy]); return <svg ref={svgRef} width={width} height={height} style={{ display: 'block' }} />; } 
Опис реалізації У коді вище ми створюємо ієрархію через d3.hierarchy, налаштовуємо layout з відступами, рендеримо фонові прямокутники для груп, заголовки, комірки з tooltip і текстом. Адаптивна поведінка гарантує читабельність на будь-якому екрані. Детальніше про алгоритм Squarify див. у документації D3.js Hierarchy.

Як реалізувати drill-down?

Drill-down — ключова функція для інтерактивних дашбордів. Функція drill-down treemap дозволяє заглиблюватись у дані. Користувач клікає по групі — і treemap перемальовується з даними дочірнього рівня. Drill-down дозволяє знаходити потрібну інформацію в 3 рази швидше порівняно з багаторівневою таблицею. Ми реалізували компонент DrilldownTreemap з хлібними крихтами для навігації назад.

function DrilldownTreemap({ data }: { data: TreeNode }) { const [currentNode, setCurrentNode] = useState<TreeNode>(data); const [breadcrumb, setBreadcrumb] = useState<TreeNode[]>([data]); function drillDown(node: TreeNode) { if (!node.children?.length) return; setCurrentNode(node); setBreadcrumb(prev => [...prev, node]); } function drillUp(index: number) { const target = breadcrumb[index]; setCurrentNode(target); setBreadcrumb(prev => prev.slice(0, index + 1)); } return ( <div> <nav className="flex gap-2 text-sm mb-3"> {breadcrumb.map((node, i) => ( <span key={i}> {i > 0 && <span className="text-gray-400 mx-1">/</span>} <button onClick={() => drillUp(i)} className={i === breadcrumb.length - 1 ? 'font-semibold' : 'text-blue-600 hover:underline'} > {node.name} </button> </span> ))} </nav> <Treemap data={currentNode} onCellClick={drillDown} /> </div> ); } 

Як обрати алгоритм розкладки?

D3.js надає чотири тайлінг-алгоритми. Порівняння:

Алгоритм Особливість Коли використовувати
treemapSquarify Комірки максимально квадратні, хороший aspect ratio За замовчуванням — найкраща читабельність
treemapSliceDice Чергує горизонтальні та вертикальні зрізи Коли дані мають строгу ієрархію за двома напрямками
treemapSlice Тільки горизонтальні зрізи Для відображення часток в одному рядку
treemapResquarify Перевикористовує минулу розкладку, мінімізуючи переміщення Для анімованого оновлення даних

Ми завжди використовуємо treemapSquarify в production — він дає найкраще співвідношення сторін. Якщо необхідна плавна зміна даних (наприклад, при оновленні котирувань), перемикаємось на treemapResquarify.

Підготовка даних для treemap

Щоб treemap працював, дані на клієнті мають бути перетворені в ієрархію. Часто API повертає плоский список рядків. Функція buildHierarchy групує їх за категоріями та підкатегоріями:

// Трансформація плоских даних в ієрархію function buildHierarchy(items: { category: string; subcategory: string; name: string; value: number }[]): TreeNode { const root: TreeNode = { name: 'root', children: [] }; items.forEach(item => { let cat = root.children!.find(c => c.name === item.category); if (!cat) { cat = { name: item.category, children: [] }; root.children!.push(cat); } let subcat = cat.children!.find(c => c.name === item.subcategory); if (!subcat) { subcat = { name: item.subcategory, children: [] }; cat.children!.push(subcat); } subcat.children!.push({ name: item.name, value: item.value }); }); return root; } 

Процес роботи та терміни

  1. Аналітика — вивчаємо структуру даних, визначаємо рівні ієрархії, метрики для площі та кольору. (1 день)
  2. Проектування — створюємо прототип на основі ваших даних, погоджуємо дизайн та інтерактив. (1 день)
  3. Реалізація — пишемо компонент на React + D3.js, налаштовуємо tooltip, drill-down, анімацію. (2-3 дні)
  4. Тестування — перевіряємо на реальних даних: великі обсяги, оновлення в реальному часі. (1 день)
  5. Деплой — інтегруємо у ваш проект, даємо інструкцію з використання. (1 день)
Готовність Термін
Базовий treemap з tooltip і drill-down 2–3 дні
З анімацією переходів і кольоровим кодуванням 4–6 днів
Повний цикл (аналітика → деплой) від 1 тижня

Типові помилки при розробці treemap

  • Ігнорування paddingTop. Заголовки груп накладаються на комірки — текст нечитабельний. Ми завжди задаємо paddingTop: 18.
  • Текст у занадто маленьких комірках. Перевіряємо ширину та висоту перед рендером, інакше — переповнення.
  • Відсутність обробки порожніх даних. Якщо вузол з value = 0, він все одно займає місце. Використовуємо фільтрацію.
  • Ігнорування treemapResquarify при анімації. Без нього кожен ререндер перемішує комірки — користувач втрачає контекст.

Що входить в роботу і чому обирають нас

  • Вихідний код компонента (React + TypeScript + D3)
  • Інтеграція з вашим API
  • Документація з налаштування та кастомізації
  • Інструкція з розгортання
  • Навчання команди (до 2 годин)
  • Гарантія 3 місяці на безперебійну роботу

Ми маємо 5+ років досвіду у візуалізації даних на складних інтерфейсах та 30+ реалізованих проектів з treemap, sunburst та іншими ієрархічними діаграмами. Ми спеціалізуємось на React D3.js візуалізації. Наші розробники сертифіковані з React та D3.js, а всі компоненти створюються з нуля, без ризиків ліцензування. Це ідеальний інструмент для візуалізації даних на сайті. Ми пропонуємо розробку treemap під ключ: від аналітики до деплою. Якщо ви хочете замовити treemap, просто напишіть нам, і ми безкоштовно оцінимо ваш проект за 1 робочий день. Просто надішліть приклад даних та вимоги до інтерактиву.