开源图编辑库 NebulaGraph VEditor 的设计思路分享
本文首发于 NebulaGraph 公众号
NebulaGraph VEditor 是一个拥有高性能、高可定制的所见即所得图可视化编辑器前端库。
NebulaGraph VEditor 底层基于 SVG 绘图,它通过合理抽象代码结构以易于二次开发和自定义绘制,极适用于审批流,工作流,血缘关系,ETL 处理,图查询等图(Graph)和网络(Network)型拓扑信息的所见即所得编辑和预览场景。在 NebulaGraph 项目中,VEditor 轻松支持了图查询,图编辑,图建模,图结构,图路径展示等可视化场景。
在 NebulaGraph 中经过不断迭代、打磨之后,VEditor 已经相对完善,开源了相关代码。基于此,今天我就来为大家分享一下它的一些设计的思路与思考。
基本特性
- 高定制性的点,线形状,一切部件皆可定制
- 扁平,简单,直接的代码架构
- 小地图,磁吸线
- 各类快捷键支持
- 历史记录
- 轻量化,压缩前仅 160kb
设计理念
最早开始接触图编辑库时,本身需求其实并不高,能满足定制 + 动画即可,但看了业界非常多的流程图库后,作为一名前端工程师的自我修养让人很难对有些过度设计的架构,臃肿的接口,复杂的类关系有好感,这与我追寻简单,精简,低耦合的代码理念相悖。因此最终决定手写一个轻量的库,并能满足各种业务场景的定制需求。VEditor 的设计理念就是希望在可定制性和可理解性的基础上能让开发者用起来更轻便,减少学习各类 API,减少依赖各类库。
技术架构
整体架构主要通过事件来做实体间的依赖管理,也建议主要通过事件来获取整个流程图的状态变化。
其中渲染流程为半自动渲染,改变流程图数据后需要手动触发渲染,其他状态下对画布进行操作会触发用户定义的 shape 渲染函数,完成自定义节点渲染节点或线渲染。
渲染实现
VEditor 主体使用 SVG 进行渲染,得益于 SVG 的声明式使用方式,其内部结构都是外置可见的,对其进行样式定制化会非常的容易,用户可以在外界直接复写相关的 SVG 样式即可,同时还可以直接操作 SVGDOM 监听相关的鼠标事件,及对某些节点添加各类动画。
在形状渲染上,主要通过暴露出来的 Shape 接口注册用户的自定义渲染函数。从这个角度上来看,VEditor 可以基于任意使用渲染技术进行渲染,只要渲染接口返回 SVGDOM 即可,这个 DOM 可以是 SVGElement 或 ForeignObject 等。因此在使用 React 或 Vue 等虚拟 DOM 框架时,非常推荐用其管理 SVG 的渲染。甚至某些情况下可以包裹一个 Canvas 来渲染 WebGL 的节点,这非常大的拓展了业务中的定制性。
除了节点外,锚点及线也支持实现对应接口后注册为 Shape 的对象渲染,在我们的 Explorer 的实际业务中利用这个特点,实现了图计算流配置支持动态增删改算法参数锚点和TP查询输入输出锚点(图 1),以及图可视化查询中边的过滤,步数渲染(图 2)。也欢迎大家申请 Explorer 试用,体验下流程图相关功能,试用地址 https://nebula-graph.com.cn/products/explorer/
整体架构主要通过事件来做实体间的依赖管理,也建议主要通过事件来获取整个流程图的状态变化。
其中渲染流程为半自动渲染,改变流程图数据后需要手动触发渲染,其他状态下对画布进行操作会触发用户定义的 shape 渲染函数,完成自定义节点渲染节点或线渲染。
数据结构设计
VEditor 的数据结构和绝大部分的同类库类似,但不会破坏用户的对象引用,也就是在用户往节点或线的对象上挂载相关数据时,会对齐进行保留,这样会方便用户实现诸如节点配置,边配置等操作后将相关数据直接挂载到点数据上。因此历史记录的 Redo,Undo 等操作会将用户的数据当做快照一同存储下来。
{
nodes:[{
uuid:"uuid",
type:"default",// shape类型
}],
lines:[{
from:"uuid",
to:"uuid",
fromPoint:0,
toPoint:0
}]
}
性能设计
众所周知,SVG 在小分辨率的渲染上,性能比 Canvas 差了许多,这也是易用性提升带来的一个缺点。尤其是在初始化时大量比较复杂或有动画的节点时,非常明显。针对这种情况,VEditor 的数据渲染部分采用的是异步流程,将锚点的渲染放到了下一个事件循环里,避免同步过程中大量获取 bbox 带来的浏览器强制重绘。在结束绘制后,缓存对应的节点数据避免重复获取。
而在添加节点或线等操作时,SVG 的 DOM 特性会让浏览器自动进行脏渲染,因此增量渲染的性能和 Canvas 差距并不,主要是进行交互和动画时导致 DOM 大量重绘会比较慢。目前设计的性能指标是 1000 个复杂形状的节点进行流畅渲染,在流程编辑类场景下是比较轻松的。
交互设计
VEdtior 默认提供了基于 Dagre 的有向图布局,但对其进行了优化,调用 Dagre 布局后,会自动对所有节点进行居中处理。同时提供了自适应大小功能,在自适应后,不同于其他库,这里会将当前节点的坐标重置为自适应的位置,在用户保存当前数据,可以直接还原自适应的位置。
VEditor 的小地图采用了 canvg 渲染,直接将 SVG 转换为 Canvas,可以保障小地图的准确性,同时减少性能损耗。在交互上则提供了全套的视图改变和拖拽功能。
未来计划
后面的规划中,VEditor 更倾向做一个不限领域的图数据编辑和渲染器,在完整缺失功能的同时,会扩大图编辑能发挥的场景并保持易用度。
- 添加框选器和多选操作
- 无向图,双箭头支持
- 性能进一步优化
GitHub 开源地址:https://github.com/vesoft-inc/nebulagraph-veditor
欢迎来给我们提建议 and 贡献 PR 呦~
交流图数据库技术?加入 NebulaGraph 交流群请先填写下你的 NebulaGraph 名片,Nebula 小助手会拉你进群哦~~
开源图编辑库 NebulaGraph VEditor 的设计思路分享的更多相关文章
- 自己动手写客户端UI库——事件机制(设计思路大放送)
在上一篇文章中我们创建了一个Button控件,并把这个控件显示在界面上, 在这一篇文章中,我们将为这个控件增加一个事件和一个方法 一:怎么绑定事件的问题 在Winform中,我们对一个按钮绑定事件的方 ...
- cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第0步---知识点总结&效果预览&设计思路
/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏.这里用3.0重写并做下笔记 **2.我也问过木头本人啦,他说:随便写.第一别全然照搬代码:第二能够说 ...
- 59.Android开源项目及库 (转)
转载 : https://github.com/Tim9Liu9/TimLiu-Android?hmsr=toutiao.io&utm_medium=toutiao.io&utm_so ...
- iOS、mac开源项目及库汇总
原文地址:http://blog.csdn.net/qq_26359763/article/details/51076499 iOS每日一记------------之 中级完美大整理 iOS.m ...
- Android开源项目及库搜集
TimLiu-Android 自己总结的Android开源项目及库. github排名 https://github.com/trending,github搜索:https://github.com/ ...
- Android 开源项目及库汇总(2)
Android 开源项目及库汇总(2) ListenToCode 2.7 2018.10.10 15:43 字数 8527 阅读 1001评论 0喜欢 29 地图 百度地图– Android百度地图 ...
- 开源图计算框架GraphLab介绍
GraphLab介绍 GraphLab 是由CMU(卡内基梅隆大学)的Select 实验室在2010 年提出的一个基于图像处理模型的开源图计算框架.框架使用C++语言开发实现. 该框架是面向机器学习( ...
- 值得推荐的C/C++开源框架和库
值得推荐的C/C++开源框架和库 转自:http://www.cnblogs.com/lidabo/p/5514155.html - 1. Webbench Webbench是一个在Linux下 ...
- 宜信开源|分布式任务调度平台SIA-TASK的架构设计与运行流程
一.分布式任务调度的背景 无论是互联网应用或者企业级应用,都充斥着大量的批处理任务.我们常常需要一些任务调度系统来帮助解决问题.随着微服务化架构的逐步演进,单体架构逐渐演变为分布式.微服务架构.在此背 ...
随机推荐
- MySQL中读页缓冲区buffer pool
Buffer pool 我们都知道我们读取页面是需要将其从磁盘中读到内存中,然后等待CPU对数据进行处理.我们直到从磁盘中读取数据到内存的过程是十分慢的,所以我们读取的页面需要将其缓存起来,所以MyS ...
- 8条github使用小技巧
1 简介 作为全球最大的开源及私有软件项目托管社区平台,github可以显著地帮助从事编程相关工作的人员提升自己的技术水平,也是费老师我日常最常浏览学习的技术类网站. github为了使得其使用更加便 ...
- GDB的简单使用一
GDB的简单使用一 一.概念 二.GDB的基本使用方法一 调试前预备知识 获取进程的内核转储 启动gdb调试 1.启动 2.设置断点 3.运行程序 4.显示栈帧 5.显示变量 6.显示寄存器 7.单步 ...
- sklearn练习1 回归
from sklearn.svm import SVR from sklearn.pipeline import make_pipeline from sklearn.preprocessing im ...
- 24.Haproxy搭建Web群集
Haproxy搭建Web群集 目录 Haproxy搭建Web群集 Haproxy简介 常见的Web集群调度器 软件类 硬件类 Haproxy应用分析 HAProxy的主要特性 HAProxy常见的8种 ...
- 关于Node.js 链接mysql超时处理(默认8小时)
备注:这是在pm2配置node环境下,超过8小时mysql自动关闭的情况下出现的解决方法:1.封装mysql.js var mysql = require('mysql'); var connecti ...
- vue大型电商项目尚品汇(后台终结篇)day06 重磅!!!
自此整个项目前后台,全部搭建完毕. 今天是最后一天,内容很多,而且也比较常用,一个图标类数据可视化,一个后台的权限管理,都是很经典的类型. 一.数据可视化 1.简介 专门的一门学科,有专门研究这个的岗 ...
- zookeeper和spring cloud版本冲突
1.使用elastic-job进行任务调度,而核心的就是使用zookeeper进行管理,但这个与spring cloud 冲突造成启动不了 |ERROR |main |SpringApplicatio ...
- java controller 异常捕获
package com.aiyusheng.framework.exception; import lombok.Data; /** * base异常类 * @author :cza * @date ...
- 001 Redis 配置
Redis缓存 1.配置Redis //Redis 配置文件 @Configuration public class RedisConfiguration { @Bean public RedisTe ...