Разработка Gantt-диаграмм для управления проектами на сайте
Планирование проекта без визуализации задач на временной шкале — прямой путь к срыву дедлайнов. Команды тратят часы на согласование сроков, а перегрузка ресурсов остаётся незамеченной до последнего момента. Разработчики часто сталкиваются с N+1 запросами при загрузке задач или с hydration mismatch в Next.js. Мы решаем это с помощью BFF и Suspense, обеспечивая плавную загрузку диаграммы без блокировки потока.
Мы разрабатываем интерактивные Gantt-диаграммы для сайтов, которые показывают зависимости, прогресс и загрузку команды. Наши инженеры имеют 10+ лет опыта в разработке UI-компонентов и гарантируют интеграцию с любым стеком (React, Vue, Angular, чистый JS).
Gantt-диаграмма отображает задачи проекта на временно́й шкале: начало/конец, зависимости между задачами, прогресс выполнения, перегруженность ресурсов. Кастомное решение даёт полный контроль над дизайном и производительностью — например, рендеринг 10 000 задач без лагов. Экономия бюджета на поддержку таких диаграмм достигает 40% по сравнению с внедрением тяжеловесных BIM-систем. Стоимость разработки окупается за счёт гибкости и отсутствия лишних функций.
Почему кастомный Gantt выгоднее готовой библиотеки?
Готовые библиотеки (DHTMLX Gantt, Bryntum Gantt) хороши для типовых сценариев, но часто имеют лишний вес и ограниченные возможности кастомизации. Кастомная разработка на D3.js или React даёт:
- оптимизацию под Core Web Vitals (LCP < 2.5 с);
- любые визуальные эффекты (анимации, темы);
- интеграцию с существующей системой авторизации и хранилищем.
Недавно мы выполнили проект для стройкомпании: требовался Gantt с ресурсным планированием и критическим путём. Готовая библиотека не позволяла настроить уникальные цвета для каждого подрядчика, а кастомный SVG-компонент вписался в дизайн-систему за 3 недели. Такое решение сократило время согласования на 30%.
Как выбрать подходящую библиотеку Gantt?
Выбор библиотеки зависит от сложности задач. Для простых проектов с 50–100 задачами подойдёт gantt-task-react — open-source компонент с базовым drag-and-drop. Если требуется отображение зависимостей и критического пути, лучше использовать DHTMLX Gantt. Для уникальных дизайнов и высокой производительности (10 000+ задач) — кастомный SVG-компонент на D3.js. В таблице ниже — рекомендации:
| Тип задач | Рекомендуемое решение | Срок |
|---|---|---|
| До 50 задач, простая вёрстка | gantt-task-react | 3–5 дней |
| 50–500 задач, зависимости | DHTMLX Gantt | 1–2 недели |
| 500+ задач, нестандартный UI | Кастомный SVG/D3 | от 2 недель |
Полный список параметров настройки
-
viewMode: Day, Week, Month -
onDateChange: обработчик изменения дат -
onProgressChange: обработчик изменения прогресса -
TooltipContent: кастомный тултип -
listCellWidth: ширина колонки с названиями задач -
ganttHeight: высота диаграммы -
todayColor: цвет подсветки текущего дня
Gantt-диаграмма позволяет видеть критический путь, выявлять перегрузки ресурсов и корректировать сроки в реальном времени. Drag-and-drop упрощает перепланирование, а прогресс-бары показывают отставание. Интеграция с CRM и трекерами задач автоматизирует обновление данных.
Что входит в работу под ключ
| Этап | Результат |
|---|---|
| Аналитика | Сбор требований, выбор библиотеки или архитектуры |
| Проектирование | Прототип взаимодействия, спецификация API |
| Реализация | Верстка компонента, интеграция с бэкендом |
| Drag-and-drop | Настройка перемещения задач, обновление дат |
| Тестирование | Unit-тесты, E2E-тесты (Cypress), проверка производительности |
| Деплой | Публикация на Vercel/выгрузка в CMS |
Как мы это делаем: стек и примеры
gantt-task-react (open-source)
npm install gantt-task-react
import { Gantt, Task, ViewMode } from 'gantt-task-react';
import 'gantt-task-react/dist/index.css';
interface ProjectTask {
id: string;
name: string;
start: Date;
end: Date;
progress: number;
type: 'task' | 'milestone' | 'project';
dependencies?: string[];
assignee?: string;
}
function ProjectGantt({ tasks, onTaskChange }: {
tasks: ProjectTask[];
onTaskChange: (task: Task) => void;
}) {
const [view, setView] = useState<ViewMode>(ViewMode.Week);
const ganttTasks: Task[] = tasks.map(t => ({
id: t.id,
name: t.name,
start: t.start,
end: t.end,
progress: t.progress,
type: t.type,
dependencies: t.dependencies ?? [],
styles: {
progressColor: t.progress >= 100 ? '#22c55e' : '#3b82f6',
progressSelectedColor: '#1d4ed8'
}
}));
return (
<div>
<div className="gantt-toolbar">
<button onClick={() => setView(ViewMode.Day)}>День</button>
<button onClick={() => setView(ViewMode.Week)}>Неделя</button>
<button onClick={() => setView(ViewMode.Month)}>Месяц</button>
</div>
<Gantt
tasks={ganttTasks}
viewMode={view}
onDateChange={onTaskChange}
onProgressChange={onTaskChange}
locale="ru"
listCellWidth="200px"
ganttHeight={400}
todayColor="rgba(59, 130, 246, 0.1)"
TooltipContent={({ task }) => (
<div className="gantt-tooltip">
<strong>{task.name}</strong>
<p>Начало: {format(task.start, 'dd.MM.yyyy')}</p>
<p>Конец: {format(task.end, 'dd.MM.yyyy')}</p>
<p>Прогресс: {task.progress}%</p>
</div>
)}
/>
</div>
);
}
Кастомный Gantt на SVG + D3
Для специфических требований (особый стиль, нестандартные ячейки) создаём компонент на D3.js. Ниже пример прототипа:
import { scaleTime } from 'd3-scale';
import { timeDay, timeWeek } from 'd3-time';
function CustomGantt({ tasks, startDate, endDate, width = 900 }) {
const timelineWidth = width - 200; // 200px на названия задач
const rowHeight = 40;
const height = tasks.length * rowHeight + 60;
const xScale = scaleTime()
.domain([startDate, endDate])
.range([0, timelineWidth]);
return (
<svg width={width} height={height}>
{/* Временны́е метки */}
{timeWeek.range(startDate, endDate).map(week => (
<g key={week.toISOString()}>
<line
x1={xScale(week) + 200} y1={0}
x2={xScale(week) + 200} y2={height}
stroke="#e5e7eb" strokeWidth={1}
/>
<text
x={xScale(week) + 204}
y={15}
fontSize={11}
fill="#6b7280"
>
{format(week, 'dd MMM')}
</text>
</g>
))}
{/* Задачи */}
{tasks.map((task, i) => {
const x = xScale(task.start) + 200;
const width = xScale(task.end) - xScale(task.start);
const y = i * rowHeight + 25;
return (
<g key={task.id}>
{/* Название */}
<text x={4} y={y + 14} fontSize={13} fill="#374151"
style={{ cursor: 'pointer' }}>
{task.name.length > 22 ? task.name.slice(0, 22) + '…' : task.name}
</text>
{/* Бар задачи */}
<rect x={x} y={y} width={width} height={24}
rx={4} fill="#93c5fd" />
{/* Прогресс */}
<rect x={x} y={y} width={width * (task.progress / 100)} height={24}
rx={4} fill="#3b82f6" />
{/* Процент */}
{width > 40 && (
<text x={x + width / 2} y={y + 16}
textAnchor="middle" fontSize={11} fill="white">
{task.progress}%
</text>
)}
</g>
);
})}
</svg>
);
}
Drag-and-drop для изменения дат
При использовании DHTMLX Gantt drag-drop встроен. Для кастомного SVG — d3-drag или @dnd-kit. Наш опыт показывает: лучше использовать @dnd-kit — он стабильнее работает с React 18.
Пошаговая инструкция по интеграции Gantt-компонента
-
Установка зависимостей. Для gantt-task-react:
npm install gantt-task-react date-fns. Для D3:npm install d3-scale d3-time. - Создание компонента. Определите интерфейс задачи и передайте массив задач в Gantt.
-
Настройка обработчиков. Реализуйте
onDateChangeиonProgressChangeдля синхронизации с бэкендом. - Добавление tooltip. Используйте встроенный TooltipContent или кастомный.
- Тестирование. Проверьте рендеринг при 1000+ задач, измерьте LCP.
Сроки
| Тип Gantt | Срок |
|---|---|
| gantt-task-react с кастомным tooltip | 3–5 дней |
| Кастомный SVG Gantt с drag-drop и зависимостями | 2–3 недели |
| Полноценный Gantt с ресурсами и критическим путём | от 4 недель |
Получите консультацию по вашему проекту — оценим сложность и предложим оптимальное решение. Закажите разработку Gantt-диаграммы и убедитесь: кастомный компонент окупается за счёт сокращения времени на согласование на 30%. Свяжитесь с нами для детальной оценки вашего проекта.







