@ngroznykh/papirus
v0.5.4
Published
TypeScript library for building interactive 2D diagrams and flowcharts on HTML Canvas
Downloads
2,850
Maintainers
Readme
Papirus
Papirus — библиотека на TypeScript для построения интерактивных 2D‑схем на HTML Canvas. Поддерживает узлы, связи, группы, стили, сериализацию, экспорт и интерактивность.
О проекте
Papirus — это движок рендера и взаимодействия с диаграммами, рассчитанный на встраивание в любой UI (SPA, статические страницы, дизайн‑системы). Библиотека поставляет:
- Рендерер (
DiagramRenderer) с системой координат, масштабированием и панорамированием. - Набор элементов (узлы/рёбра/группы) и базовые типы.
- Менеджеры взаимодействий (выделение, перемещение, соединение, история).
- Контекстное меню и поиск/фильтрация.
- Базовые анимации и анимированный поток рёбер.
- Темизацию и стили через
StyleManager. - Оверлеи (сетка, миникарта, линейки, направляющие) и утилиты экспорта.
Установка
npm install @ngroznykh/papirusТребования
- Node.js
>=18 - Современный браузер с поддержкой Canvas API (Chrome, Edge, Firefox, Safari)
Быстрый старт
import { DiagramRenderer, RectangleNode, Edge } from '@ngroznykh/papirus';
const renderer = new DiagramRenderer('#canvas', {
width: 900,
height: 600,
backgroundColor: '#fafafa',
});
const nodeA = new RectangleNode({ x: 100, y: 100, width: 140, height: 60, label: 'Start' });
const nodeB = new RectangleNode({ x: 360, y: 100, width: 140, height: 60, label: 'Process' });
renderer.addNode(nodeA);
renderer.addNode(nodeB);
renderer.addEdge(new Edge({
from: { nodeId: nodeA.id },
to: { nodeId: nodeB.id },
type: 'bezier',
}));
renderer.enableInteractions();Документация
Возможности
Интерактивность
Встроенный InteractionManager включает:
- drag/select/connect/undo/redo/copy/paste
- Панорамирование по пустому месту канваса
- Zoom колесом, pinch‑to‑zoom, two‑finger pan
- Smart-align к другим фигурам при перетаскивании (с направляющими)
const interactions = renderer.enableInteractions({ gridSize: 20, snapToGrid: true });
interactions.navigation.fitToView();
interactions.drag.setAlignmentEnabled(true);Создание связи по умолчанию: перетягивание от одной точки (anchor) узла к другой, без модификаторов.
Горячие клавиши по умолчанию:
Delete/Backspace— удалить выделениеCtrl/Cmd + C/Ctrl/Cmd + V— копировать/вставитьCtrl/Cmd + Z— отменаCtrl/Cmd + YилиCtrl/Cmd + Shift + Z— повтор
Для редактируемой полилинии:
type: 'editable-polyline'поддерживает draggable точки перелома.- На серединах сегментов доступны маленькие
+для добавления новых точек. - Двойной клик по точке перелома удаляет её.
- Для точек перелома работают snap к сетке и осевые магниты при перетаскивании.
Элементы и группы
const group = new Group({ label: 'Main Flow', padding: 16 });
group.addChild(nodeA);
group.addChild(nodeB);
renderer.addGroup(group);
const node = new RectangleNode({
x: 20, y: 20, width: 120, height: 60,
ports: [{ type: 'input', position: 'left' }],
contentInset: { top: 8, right: 10, bottom: 8, left: 10 },
label: {
text: 'Start service',
inset: 8,
style: { align: 'left', verticalAlign: 'top' },
},
icon: {
source: '/icons/start.svg',
fit: 'contain',
scaleWithBounds: true,
placement: 'top-right',
inset: 6,
},
});Компоновка контента и фон подписи связи
Компоновка узла строится в два шага:
contentInsetзадаёт контентную область внутри границ фигуры;label.insetзадаёт внутренний отступ текста внутри контентной области.
Иконка и текст используют одну контентную область:
- позиция иконки задаётся через
icon.placementиicon.inset; - выравнивание текста задаётся через
label.style.alignиlabel.style.verticalAlign.
Для подписей связей доступен фон через labelBackground:
const edge = new Edge({
from: { nodeId: nodeA.id },
to: { nodeId: nodeB.id },
label: 'API call',
labelOffset: 12,
labelBackground: {
color: '#ffffff',
opacity: 0.9,
borderRadius: 6,
},
});Стили
StyleManager применяет темы и классы к узлам/рёбрам/тексту/портам/группам.
const styles = new StyleManager('dark');
styles.registerClass({
name: 'error',
node: { fillColor: '#fee2e2', strokeColor: '#dc2626' },
text: { color: '#991b1b' },
});
renderer.setStyleManager(styles);Доступны готовые темы: DEFAULT_THEME, DARK_THEME.
Сериализация
import { Serializer } from '@ngroznykh/papirus';
const serializer = new Serializer(renderer, {
nodeFactory: (data) => new RectangleNode(data),
edgeFactory: (data) => new Edge(data),
});
const json = serializer.toJSON(true);
serializer.fromJSON(json);Экспорт
import { ImageExporter, SvgExporter } from '@ngroznykh/papirus';
const imageExporter = new ImageExporter(renderer);
await imageExporter.download('diagram.png', { scale: 2 });
const svgExporter = new SvgExporter(renderer);
await svgExporter.download('diagram.svg');Оверлеи
import { GridOverlay, MiniMap } from '@ngroznykh/papirus';
renderer.use(new GridOverlay({ gridSize: 20 }));
renderer.use(new MiniMap({ width: 180, height: 120, padding: 12, contentMargin: 200 }));Доступны также RulersOverlay, GuidesOverlay, AutoLayout, AutoRouting, alignNodes, distributeNodes.
Интеграции
Papirus не привязан к конкретному фреймворку и может быть встроен в Vue/React/Svelte/vanilla приложения.
Пример
См. интерактивные локальные примеры в examples/index.html.
Версионирование и стабильность API
Papirus следует Semantic Versioning.
Текущая мажорная версия 0.x, поэтому между минорными релизами возможны изменения API.
Все важные изменения фиксируются в CHANGELOG.ru.md.
Разработка
npm install
npm run devПолезные команды:
npm run typecheck # Проверка типов TypeScript
npm run lint # ESLint
npm run format # Форматирование Prettier
npm run build # Сборка библиотеки
npm run test # Запуск тестов
npm run test:coverage # Тесты с покрытиемContributing
См. CONTRIBUTING.md.
Ключевые файлы для open-source процесса:
- CONTRIBUTING.md / CONTRIBUTING.ru.md
- SECURITY.md / SECURITY.ru.md
- CODE_OF_CONDUCT.md / CODE_OF_CONDUCT.ru.md
Лицензия
Проект использует dual licensing:
AGPL-3.0-or-laterдля open-source использования- Коммерческая лицензия для проприетарного/закрытого коммерческого использования
См.:
