电信网结构 (telecommunication network structure) 是指电信网各种网路单元按技术要求和经济原则进行组合配置的组合逻辑和配置形式组合逻辑描述网路功能的体系结构, 配置形式描述网路单元的邻接关系, 即以交换中心 (或节点) 和传输链路所组成的拓扑结构常见的网络拓扑结构有星型结构总线结构环形结构树形结构网状结构混合型拓扑以及蜂窝拓扑结构等, 本文的例子主要描绘的是总线型拓扑, 在显示上相对其他的结构类型来说更清晰明了, 绘制起来也非常容易
虽然题目起的名字是电信网络拓扑图, 几乎所有的拓扑图都能涵盖, 例如基本网络图, 网络拓扑图, 机架图, 网络通信图, 3D 网络图等等
效果图如下:
这个图看起来挺简单的, 代码也少, 但是内容不少
首先, 机柜 01 机柜 02 机柜 03 都是 ht.Group 组类型, ht.Group 类型用于作为父容器包含孩子图元, 在 GraphView 拓扑图 (http://www.hightopo.com) 上可通过双击进行展开合并, 合并时会自定隐藏子孙图元节点, 如果有子节点有连线连接到外部时, 合并的 Group 将代理进行连接 Group 的移动会带动孩子节点跟随, 孩子的位置和大小变化也会影响 Group 的展开图形和 position 位置
这边提到一个代理连线的问题, 代理两个字可以很好地表明代理连线意义实际上就是如果组内部的节点与组外部的节点有连线, 那么在组合并的时候, 会在这个组会代理与外部节点之间的连线, 这个就是代理连线我们拿机柜 02 来说吧, 机柜 02 内部有一个电脑与内部网络交换机之间有两条连线, 那么当我们双击机柜 02 合并时, 实际上就相当于机柜 02 与内部网络交换机之间有两条连线了
那么, 我们来看看如何绘制这个组以及组内部的节点吧, 先创建机柜 02 的 Group 节点, 因为整个例子我创建了三个 Group 节点, 而且创建的方式都类似, 因此把创建组的代码封装起来复用:
- function createGroup(name, x, y) {
- var group = new ht.Group();// 组类型 实际上也是一个节点
- group.setExpanded(true);// 设置展开组
- group.setName(name);// 设置组的名字
- group.s({// 设置组的样式 style
- 'group.title.background': 'rgba(14,36,117,0.80)',// 组展开后的 title 背景颜色, 仅对 group.type 为空的类型起作用
- 'group.background': 'rgba(14,36,117,0.40)',// 组展开后的背景颜色
- 'group.title.align': 'center'// 组展开后的 title 文字水平对齐方式, 默认值为'left', 可设置为 center 和 right
- });
- group.setPosition(x, y);// 设置组的位置
- group.setImage('images / 服务器. json');// 设置拓扑上展现的图片信息, 在 GraphView 拓扑图中图片一般以 position 为中心绘制
- dataModel.add(group);// 将创建的组节点添加进数据容器中
- return group;
- }
组是可以通过双击展开合并的, 展开的时候显示的是一个有标题栏的框(当然这些都是可以自定义的), 合并的时候就显示上面代码中设置的 group.setImage 中的图片
所有机柜内部的节点都是 ht.Node 类型的节点, 所以我也封装了一下:
- function createNode(image, parent, x, y) {
- var node = new ht.Node(); // 创建一个 Node 节点
- if (image) node.setImage(image); // 设置节点的显示图片
- if (parent) node.setParent(parent); // 设置节点的父亲
- if (x && y) node.setPosition(x, y); // 设置节点的位置
- dataModel.add(node); // 将节点添加进数据容器中
- return node;
- }
生成机柜 02:
- cabinet = createGroup('机柜 02', 146, 445);// 创建机柜 02
- createNode('images / 正常. json', cabinet, 78, 440).s('label', '数据监控分析系统');// 创建带有正常图片的节点, 并设置这个节点的文字为数据监控分析系统
因为连线需要的是源节点以及终节点, 这边源节点是中间的内部网络交换机, 我们再创建这个节点:
- var line = createNode();// 创建一个节点
- line.setSize(725, 20);// 设置节点大小
- line.setPosition(310, 325);// 设置节点位置
- line.s({// 设置节点的 style 属性
- 'shape': 'roundRect',// 决定 shape 的形状, 默认值为空, 代表用 image 绘制 roundRect 四周圆角矩形
- 'shape.background': 'rgba(14,36,117,0.80)',// 背景填充颜色, 为 null 代表不填充背景
- 'shape.border.color': '#979797',// 边框颜色
- 'shape.corner.radius': 10,// 该参数指定 roundRect 类型的圆角半径, 默认为空系统自动调节, 可设置正数值
- 'label': '内部网络交换机', // 文字内容, 默认为空
- 'label.position': 45,// 文字内容, 默认为空
- 'label.offset.x': 50,// 文字水平偏移, 对于 Edge 意味着沿着连线方向水平偏移
- 'label2': '内部网络交换机',//HT 默认除了 label.* 的属性外, 还提供了 label2.* 的属性, 用于满足一个图元需要显示双文字的情况
- 'label2.position': 48,
- 'label2.offset.x': 50,
- 'label2.offset.y': 2,
- });
不知道你们有没有注意到, 有一个 label2 的样式属性, 这个是 HT 为了能在一个节点上添加两个 label 文本而增加的功能, label 属性和 label2 的属性是完全相同的, 只要在设置属性的时候用 label 和 label2 区分开来就可以
源节点和终节点都具备了, 可以制作连线了:
- createEdge(line, createNode('images / 电脑. json', cabinet, 185, 450), 'rgb(30,232,178)', -100, true);
- // 参数 1 源节点, 参数 2 终节点, 参数 3 连线颜色, 参数 4 连线起始点的水平偏移, 参数 5 是否创建两条连线
还有一点有趣的, 交换机的部分, 最左侧蓝色方形的节点和中间长条的节点并不是一体的, 而是分离的, 但是我通过 setHost 进行节点与节点间的吸附, 然后反吸附回来, 这样操作上就相当于这两个节点是一体的:
- var exchange = createNode('images / 交换机. json', null, -53, 313);
- exchange.setHost(line);// 设置吸附
- line.setHost(exchange);// 反吸附 又设置 line 的吸附为 exchange
因为 HT 会按照节点添加进数据容器中的顺序来进行层次的排列, 我的交换机是在 line 的添加之后的, 所以默认交换机的节点会显示在 line 之下, 我们将默认的层级显示关闭, 并设置交换机 exchange 显示在数据容器的顶部:
- dataModel.setAutoAdjustIndex(false);// 将自动调整 data 在容器中索引顺序的开关关闭
- dataModel.sendToTop(exchange);// 将 data 在拓扑上置顶
代码解释就是这些还有不懂的可以留言或者私信我也可以, 大家可以一起探讨
来源: https://segmentfault.com/a/1190000013181154