在过去的几年里,我更多地参与了文档工作。 编写有关特定系统如何工作的解释性文本通常非常简单。 绘制一个图表来显示所有关键对象以及这些对象之间的连接也非常容易。
但最有问题的方面是保持该文档的最新状态。 文字可以,但是图表……因为…… 所有文档均在线,即html 格式,然后文本附有 gif/jpeg/png 图片,这些图片实际上显示了图表。 图表是在各种程序中绘制的,例如 Visio 或 ladraw.io 的在线服务。 然后将图表导出为图形格式并将其附加到 html。 这很简单。
有什么问题吗?
这些方案通常很简单。 更准确地说,不是很复杂。 是的,对象的数量是十几两个,连接的数量大约是相同的。 加上签名,一些名称。 简单的方案可以用语言描述,但太复杂的方案,咳咳…… (c)“他们不会理解,先生。” 方案有很多,需要定期、间歇性地对其进行更改,即不断地,因为他们关注我们产品的开发。
您可以嵌入服务的 html。 你尝试过吗?
是的,当然。 例如,我喜欢 gliffy.com 的图形。 但要进行更改,您需要访问第三方服务并在那里进行编辑。 而且将更正委托给同事也更加困难。
怎么办?
最近我在Github上的推荐中发现了一个存储库
顺便说一下,我并不完全用 html 编写文档。 通常,文档是一组带有 Markdown 文本的文件,然后由某些引擎(例如 Wintersmith)将其转换为成熟的文档站点。 或者维基系统。
事实证明非常方便:我们已经编写了文本,然后打开 script 标签,其中描述了该方案的 JS 代码。
又怎么了?
我喜欢这个存储库,但这并不是使用代码或文本表示绘制图表的唯一示例。 (在文章的末尾,将提供我在主题图上通过 Google 搜索到的项目和文章的链接作为代码。)
而且我并不是唯一一个编辑文档的人。 有时同事也会做出贡献 - 更正单词、更改描述、插入新图片。
因此,我希望以可读、可理解的文本格式查看该图,不需要很长的学习曲线。 在某些地方,您甚至可以简单地复制粘贴来加快添加新电路的速度。
另一位同事指出,代码当然很好,但如果使用结构,一切都可以非常严格和富有表现力。
因此,我尝试将该图想象为一组几个小数组,用于描述节点、连接、节点组以及节点的位置。 事实证明,以我的拙见,相当方便,当然,味道和颜色......
这是一个数组中的图表吗?
- 每个节点由唯一标识该节点的标识符来描述。
- 您还可以向节点添加图标并添加铭文。
- 您可以指定两个节点之间的关系。
- 为了在图表上进行通信,您可以设置颜色和铭文。
- 通信方向定义为从源到目标。 源和目标由节点标识符指示。
- 可以将一个或多个节点添加到组中。
- 还可以从组和到组指定关系。
使用这些简单的规则,我们得到下图。 只是? 相当。
通过下面的js代码来描述。 这里最主要的是 elements 对象。 其中节点被指示为-节点,边缘-连接。
const elements = {
nodes: [ // описываем узлы
{ id: 'client', type: 'smartphone', label: 'Mobile App'},
{ id: 'server', type: 'server', label: 'Main Server'},
{ id: 'db1', type: 'database', label: 'DB 1'},
{ id: 'db2', type: 'database', label: 'DB 2'},
],
edges: [ // указываем связи
{ source: 'client', target: 'server', label: 'request' },
{ source: 'server', target: 'db1', label: 'request' },
{ source: 'server', target: 'db2', label: 'request' },
],
};
Diagram('scheme1', elements);
当然,电路图不是我自己想出来的,而是使用了库
好的,这是一个简单的例子。 还能更复杂一点吗?
是的,请。 为了表示位置,我们使用位置,为了表示组,我们表示组中的组列表,并且元素本身具有组属性。
这是代码:
<div id="scheme5" style="height:500px;width:800px;"></div>
<script>
const elements5 = {
groups: [
{ id: 'g1', label: 'Группа сервисов 1'},
{ id: 'g2', label: 'Группа сервисов 2'},
],
nodes: [
{ id: 'man1', type: 'person', label: 'Человек'},
{ id: 'client', type: 'smartphone', label: 'Смартфон'},
{ id: 'agent-backend', type: 'server', group: 'g1', label: 'agent-backend'},
{ id: 'web', type: 'server', group: 'g1', label: 'Приложение admin'},
{ id: 'www', type: 'server', group: 'g1', label: 'страница загрузки'},
{ id: 'mongodb1', type: 'database', group: 'g1', label: 'Mongo DB 1'},
{ id: 'mongodb2', type: 'database', group: 'g1', label: 'Mongo DB 2'},
{ id: 'runner-integration1', type: 'worker', group: 'g1', label: 'отправка'},
{ id: 'runner-integration2', type: 'worker', group: 'g1', label: 'отправка'},
{ id: 'api', type: 'server', group: 'g1', label: 'API'},
{ id: 'server2', type: 'server', group:'g2', label: 'сервер'},
{ id: 'otherServer', type: 'server', group:'g2', label: 'сервер'},
{ id: 'firebase', type: 'cloud', label: 'Google Firebase'},
],
edges: [
{ source: 'client', target: 'agent-backend', label: 'json', color: 'red' },
{ source: 'agent-backend', target: 'mongodb1', color: 'red' },
{ source: 'agent-backend', target: 'mongodb2', color: 'red' },
{ source: 'mongodb1', target: 'runner-integration1', label: 'данные' },
{ source: 'mongodb2', target: 'runner-integration2', label: 'данные' },
{ source: 'mongodb1', target: 'web', label: 'данные для отображения' },
{ source: 'runner-integration1', target: 'server2', label: 'данные' },
{ source: 'runner-integration2', target: 'otherServer', label: 'данные' },
{ source: 'api', target: 'firebase', label: 'запросы', color: 'blue', },
{ source: 'firebase', target: 'client', label: 'push', color: 'blue'},
{ source: 'server2', target: 'api', label: 'уведомления', color: 'blue'},
{ source: 'man1', target: 'client', },
],
positions: [
{ id: 'client', row: 2, col: 1,},
{ id: 'agent-backend', row: 2, col: 3,},
{ id: 'web', row: 6, col: 3,},
{ id: 'www', row: 1, col: 3,},
{ id: 'mongodb1', row: 1, col: 4,},
{ id: 'mongodb2', row: 2, col: 5,},
{ id: 'runner-integration1', row: 3, col: 3,},
{ id: 'runner-integration2', row: 4, col: 3,},
{ id: 'api', row: 5, col: 3,},
{ id: 'server2', row: 6, col: 7,},
{ id: 'otherServer', row: 4, col: 7,},
{ id: 'firebase', row: 5, col: 1,},
{ id: 'logger', row: 2, col: 7,},
{ id: 'crm', row: 5, col: 8,},
],
};
Diagram('scheme5', elements5, {layout: 'grid'});
</script>
一方面,这样的方案几乎就是笔记本电脑上的几屏代码,另一方面,json 的结构让你可以类比快速地填写所有数据,并且可以复制粘贴。
为什么位置与节点分开放置?
更舒服。 首先我们指定节点。 然后我们可以指定几个组并在节点中指示它们。 然后我们指定连接。 只有这样,当主要对象及其之间的连接都存在时,我们才能在图表上确定这些对象的位置。 或相反亦然。
没有职位可以吗?
没有职位也是可能的。 但它会有点皱巴巴的;你可以在示例中看到这个选项。 这是因为 cytoscape 有一个节点位置算法
位置也可以在战舰样式中指定。 那些。 一个节点位于a1,另一个节点位于d5。 它特别有助于 cytoscape 使画布上的对象可移动,即我们可以移动它们,查看不同的布局选项,然后在代码中修复我们喜欢的元素的排列。
一般来说,这是可以理解的。 你也可以尝试一下吗?
当然,为了快速创建电路,我给自己做了一个小
你尝试过吗? 您现在可以将其添加到您的页面。
然后再次:
1. 连接脚本
<script src="https://unpkg.com/@antirek/[email protected]/dist/code-full.min.js"></script>
2. 添加代码到html
<div id="scheme1" style="height:300px;width:800px;"></div>
<script>
const elements = {
nodes: [
{ id: 'client', type: 'smartphone', label: 'Mobile App'},
{ id: 'server', type: 'server', label: 'Main Server'},
{ id: 'db1', type: 'database', label: 'DB 1'},
{ id: 'db2', type: 'database', label: 'DB 2'},
],
edges: [
{ source: 'client', target: 'server', label: 'request' },
{ source: 'server', target: 'db1', label: 'request' },
{ source: 'server', target: 'db2', label: 'request' },
],
};
Diagram('scheme1', elements);
</script>
3. 我们将代码编辑为我们需要的图表(我认为这比画猫头鹰更容易:)
更多详情请参见
结果如何呢?
我实现了我的目标 - 将内联图添加到文档中,格式非常简单且易于理解。 它不适合超级电路,但对于解释连接结构的小型电路来说,绝对没问题。 随着时间的推移,您始终可以快速调整和更改某些内容。 是的,同事可以自己在码头上纠正某些内容,至少是对象的标题,无需特殊培训))
有什么可以改进的?
当然,这里有很多选择。 添加其他图标(所有现有图标都内联添加到脚本中)。 选择一组更具表现力的图标。 可以指定连接线的样式。 添加背景图像。
你觉得呢
我已经有一些在问题中实现的想法,你也可以在评论中添加你的想法。
我的解决方案绝对适用于一小部分问题,也许您会找到一种更方便的工具来通过简单地编码来绘制图表 - 正如他们所说的“以代码形式显示您的图表”
很好的选择 很棒的服务 (9种图表在线编辑器)当然,mermaid.js - 如果您喜欢超级详细和复杂的图表,那么您一定会欣赏这个项目:
去画网
来源: habr.com