我为 Angular 构建了一个配置驱动的图形编辑器——以下是我的收获
I’m happy to translate the article for you, but I’ll need the full text you’d like translated (the body of the article). Could you please paste the content you want converted to Simplified Chinese? Once I have it, I’ll keep the source line unchanged and translate the rest while preserving all formatting, markdown, and code blocks.
现有工具的问题
大多数图形库分为两类。要么功能强大 但 复杂,需要你学习全新的渲染范式;要么简单 但 带有强烈的主观倾向,强迫你的数据适应它们的结构。
我想要的是一种在 Angular 中感觉原生的工具——能够理解 signals、模板和变更检测,并且将可视化表示与我的领域逻辑分离。
介绍 @utisha/graph-editor
@utisha/graph-editor 是专为 Angular 19+ 构建的可视化图编辑器。它使用 SVG 渲染,利用 dagre 进行布局,并通过 signals 保持全部响应式。没有 RxJS,没有 canvas,也没有繁琐。
核心理念很简单:通过配置而不是代码来定义节点和边的外观。库负责平移、缩放、选择和渲染。你只需专注于你的数据。
快速开始
安装包
npm install @utisha/graph-editor
使用组件
import { Component, signal } from '@angular/core';
import {
GraphEditorComponent,
Graph,
GraphEditorConfig,
} from '@utisha/graph-editor';
@Component({
selector: 'app-editor',
standalone: true,
imports: [GraphEditorComponent],
template: `
`,
})
export class EditorComponent {
/** Configuration for the editor */
config: GraphEditorConfig = {
nodes: {
types: [
{
type: 'task',
label: 'Task',
icon: '⚙️',
component: null,
defaultData: { name: 'New Task' },
size: { width: 180, height: 80 },
},
],
},
edges: {
component: null,
style: {
stroke: '#94a3b8',
strokeWidth: 2,
markerEnd: 'arrow',
},
},
canvas: {
grid: { enabled: true, size: 20, snap: true },
zoom: {
enabled: true,
min: 0.25,
max: 2,
wheelEnabled: true,
},
},
};
/** Reactive graph state */
graph = signal({
nodes: [
{
id: '1',
type: 'task',
data: { name: 'Start' },
position: { x: 100, y: 100 },
},
{
id: '2',
type: 'task',
data: { name: 'End' },
position: { x: 350, y: 100 },
},
],
edges: [{ id: 'e1', source: '1', target: '2' }],
});
}
就这样——现在你拥有一个可拖拽、可缩放的图表,它会响应你的 signal 更改。
有何不同
- 基于配置的架构 – 在单一配置对象中定义节点类型、边的样式和主题。组件保持简洁,图形逻辑可测试,业务模型不受影响。
- 面向 Angular 19+ 构建 – 使用 signals 进行状态管理和变更检测。无需 RxJS 订阅,无内存泄漏担忧,也不需要
async‑pipe。 - SVG 渲染 – 在任何缩放级别下都保持清晰,可选中文本,CSS 样式开箱即用。甚至可以通过
ngComponentOutlet插入自定义 Angular 组件。
主题预设
| 主题 | 描述 |
|---|---|
| Default | 干净的白色背景,适用于文档和图示 |
| Compact | 冷色蓝灰配点状网格,适合密集工作流 |
| Detailed | 温暖的琥珀色调,适用于流程图和图表 |
| Dark | 炭黑背景加青色点缀,适用于开发者工具 |
注意: 你可以完全重新设计编辑器的样式以匹配任何品牌。下面是我为专有应用构建的截图示例:
关键特性
- ✅ Custom node rendering with
ng-templateorngComponentOutlet→ 自定义节点渲染 使用ng-template或ngComponentOutlet - ✅ Edge path strategies: straight, bezier, step → 边路径策略:straight、bezier、step
- ✅ Undo/redo with full state history → 撤销/重做,具备完整状态历史
- ✅ Multi‑select (Shift‑click or box selection) → 多选(Shift‑点击或框选)
- ✅ Node resize handles → 节点缩放手柄
- ✅ Auto‑layout powered by dagre → 自动布局,由 dagre 提供支持
- ✅ Keyboard shortcuts (Delete, Ctrl + Z, Ctrl + Shift + Z) → 键盘快捷键(Delete、Ctrl + Z、Ctrl + Shift + Z)
- ✅ Lightweight – only Angular and dagre as dependencies → 轻量级 – 仅依赖 Angular 和 dagre
试一试
实时演示:
StackBlitz:
npm:
GitHub:
我学到了什么
构建 @utisha/graph-editor 让我掌握了以下技巧:
- 利用 Angular 信号实现真正的响应式 UI,省去 RxJS 的开销。
- 将渲染逻辑(SVG)与领域模型分离,使库可以轻松在任何项目中使用。
- 提供以配置为中心的 API,既保持灵活,又足够有指导性,能够快速上手。
试一试吧,告诉我你的感受!
Building this reinforced something I already suspected: Angular's signal‑based reactivity is genuinely pleasant to work with. Building a complex interactive component without RxJS felt almost too simple. No `BehaviorSubject`, no `distinctUntilChanged`, no manual subscription cleanup. Just signals and effects, and the framework handles the rest.
The configuration‑driven approach paid off too. Early on I tried embedding node‑rendering logic directly in the component. It got messy fast. Moving to a config object with render strategies made the library flexible enough for my use case while staying simple for quick prototypes.
接下来
- 该库已在 v1.0.7 稳定,可用于生产环境。
- 我正在编写更完善的文档,增加除 Dagre 之外的布局算法,并可能实现用于自定义边类型的插件系统。
如果你在构建工作流工具、流程设计器,或任何需要在 Angular 中进行可视化图编辑的应用,欢迎尝试。这个库是我因为自己的需求而创建的——也许你也会需要它。
- ⭐ 给仓库加星 如果你觉得它有用。
- 🐞 提交 issue 如果出现问题。
- 🤝 欢迎提交 Pull Request。


