likes
comments
collection
share

用JTopo在前端绘制网络拓扑图

作者站长头像
站长
· 阅读数 23

----------------------------------------------------------------------------------------------

正文

项目中遇到要在网页中绘制网络拓扑图的需求,要求节点具备点击、拖拽、缩放等交互功能,并且可以显示/隐藏详细信息,数据是设备实时上报来的。

一、工具的选择

1.经过在网上搜索,首先找到了一个叫Qunee的,感觉非常合适,然而这个库是收费的,以个人开发者申请还需要签非盈利的协议,只能放弃。有兴趣的可以自己区官网看一看www.qunee.com

2.然后又找到一个叫D3(Data-Driven Documents)的,是一款很好的做数据可视化的js库,而且免费。唯一小缺憾是自由度很高,所以相对于一些开箱即用、API很简单的库来说自学难度稍微高一些。准备有时间了自学一下。官网是D3.js - Data-Driven Documents

3.最后在单位旧项目的代码中找到了实现类似功能的js库,叫JTopo,搜了一下是开源免费的,看了一下demo很好上手,果断选择该工具实现功能。

二、下载和简介

JTopo 是一款完全基于HTML5 Canvas的数据关系+交互式图形库。 可以快速创建一些拓扑关系图。

Github链接: GitHub - wuln/jTopo: draw the network topology by javascript

Github上有一个demo,包含html、js、css和图片,但是时间显示是5年前了,下载下来之后对照着官网最新的文档发现很多方法、关键字都不相同,参考价值不大。

官方网站 jtopo 一个好用的交互式HTML5图形库

离线JS文件下载地址 jtopo 更新下载

项目的完整效果不能展示,自学过程中完成的demo的效果图如下,我将在下面介绍该js库的入门使用和一些功能的实现方法。

用JTopo在前端绘制网络拓扑图

三、入门程序

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="js/jquery.js"></script>
    <script type="text/javascript" src="js/jtopo-1.0.4_trial-min.umd.js">
</script>
</head>
<body>
    <!-- 用于渲染显示的div -->
    <div id="divId" style="height:600px; width:600px;">
        <!-- <canvas id="target" style="height:400px; width:600px;"></canvas> -->
    </div>
    <script>
        // 频繁用到的对象名字先导入,减少打字数
        var Stage = jtopo.Stage;
        var Layer = jtopo.Layer;
        var Node = jtopo.Node;
        var Link = jtopo.Link;
        // 根据一个DIV的id创建顶层对象:Stage
        // 注:'divId' 需换成你页面实际的div的id或者dom对象
        var stage = new Stage('divId');
        // 一个Stage下面可以有多个'层',Layer
        // 多个Layer可以配合,比如有背景层,有动画层,有交互、展示层等
        var layer = new Layer();
        // 一般步骤,将Layer放入到‘场景’中
        stage.addChild(layer);
        // 创建一个节点:new Node('文本', x,y,宽度, 高度)';
        // 所有参数都是可选项,也可以稍后赋值
        var fromNode = new Node('From', 200, 200, 48, 48);
        // 设置图片
        fromNode.setImage('imgs/server_icon.png');
        // 创建另一个节点
        var toNode = new Node('To');
        // x,y
        toNode.setXY(400, 200);
        // 大小
        toNode.resizeTo(48, 48);
        toNode.setImage('imgs/server_icon.png');
        // 连线 new Link('文本',开始节点,结束节点);
        var link = new Link('Link', fromNode, toNode);
        // 设置样式:粗细
        link.setStyles('lineWidth', 2);
        // 将节点和连线都加入到Layer中
        layer.addChild(fromNode);
        layer.addChild(toNode);
        layer.addChild(link);
        // 按画布居中
        stage.translateToCenter();
        // 不显示工具栏(当前版本工具栏样式未打包进去)
        stage.hideToolbar();
        // 最后一步:显示
        stage.show();
    </script>
</body>
</html>

入门程序的效果图如图所示,默认具有选中高亮效果并且节点可以拖拽。

用JTopo在前端绘制网络拓扑图

四、核心对象介绍

jtopo的核心对象之间存在层级结构。

1. 顶层对象(Stage)

最顶层的为Stage,管理一个或者多个Layer,可以对Layer进行管理:添加、移除。并且提供一些常规性的交互功能,比如:鼠标缩放、视图模式变换(普通、框选、拖拽、编辑、锁定)、按画布居中、导出图片等功能。

2. 层对象(Layer)

Layer 是一个抽象对象,默认是完全透明的,上层对象为Stage。一个Layer下面可以有多个Node、Link对象,Node、Link对象只有放入Layer后才可能被绘制出来。Layer的frames属性用来设置绘制帧率,即每秒的重绘次数。

Layer 可以被平移、缩放,用户可以通过鼠标在画布上的拖拽 和 鼠标滚轮完成,也可以通过API来修改Layer的x、y坐标和缩放系数scaleX和scaleY实现同等效果。

一个Layer对象对应一个Canvas,多个Layer常用于画面逻辑分层,比如有的层绘制速度较慢,有的层绘制速度较快,有的层作为背景层,有的作为动画层。

需要通过Stage对象的addChild方法放入Stage中。

3. 节点对象(Node)

用户操作的核心两个对象Node 、Link之一。

Node默认是一个矩形,有坐标(x,y) 和 宽高尺寸(width、heigh)。它是可以作为容器使用,里面可以放其他元素,也就是说可以嵌套,内部的元素同样通过addChild方法放进作为容器的Node中。

可以指定一个文本字符串,默认显示在中矩形的下面。

外观可以通过setStyles方法设置,核心的外观属性有:边框颜色、填充颜色、字体颜色、字体(大小、加粗等CSS Font支持的都可以)、圆角。

需要通过Layer对象的addChild方法放入Layer中。

4.连线对象(Link)

用户操作的核心两个对象之一。

Link是连线,有起始点和结束点,一般用来表示关系、流向等。

可以指定一个文本字符串,默认显示在连线的中间。

外观同样通过setStyles方法设置,核心的外观属性有:颜色、线条粗细、字体颜色、字体(大小、加粗等CSS Font支持的都可以)。

和Node一样需要放入Layer中。

五、文本和定位

文字定位由三个核心属性控制:1. 位置 2. 文本对齐方式 3. 文本基线

1.位置

用JTopo在前端绘制网络拓扑图

节点文本的位置默认为‘cb’

线在连接时用的表明位置的关键字也是这些,额外再加一个‘edge’。‘edge’表明线连在端点的边上,具体连接点由两个端点的相对位置决定。

2.文本对齐方式

用JTopo在前端绘制网络拓扑图

3.文本基线

用JTopo在前端绘制网络拓扑图

除了这三个,也可以通过textOffsetX和textOffsetY属性自定义偏移量。

六、自动布局

该库提供了一些预先定义好的布局样式:1.树形布局(TreeLayout)2.网格布局(GridLayout)3.圆形布局(CircleLayout)4.斥力布局(ForceDirectLayout)5.自由边界布局(AutoBoundLayout)

用法很简单,布局同样是通过new来创建,要对哪些元素使用这个布局,则调用布局对象的doLayout(elements)方法即可,斥力布局除外。详细用法可以参考官网或自己进行尝试。

比如树形布局

//方向:up、down、left、right,决定树朝哪个方向生长
//左右间隔量 40, 上下间隔量80
var treeLayout = new jtopo.TreeLayout('down', 40, 78);
treeLayout.doLayout(layer.children);

斥力布局要从根节点应用布局

效果为:用JTopo在前端绘制网络拓扑图

var layout = new ForceDirectLayout(rootNode, stage.width, stage.height);
var timer = setInterval(function () {
    // 斥力布局需要多次调用applyForce迭代
    // 还有一些参数可以调节,本例为了保持简单暂略去
    layout.applyForce();
}, 10);

七、事件处理

通过addEventListener或者on进行绑定,removeEventListener和off进行解绑,这里不再详细介绍。有一点需要说明:jQuery中用on()进行事件处理可以一次给多个事件绑定同一个监听器,比如on("click mouseout", function1),但是这里必须一个一个绑。

八、动画效果

1.位置计算

Node 或 Link对象有一个getPoint(t)方法, t取值范围:[0-1],可以获取对象上某一点的坐标。

对于Node的来说,一周就是0-1,对于Link来说从起点到终点就是0-1。

用JTopo在前端绘制网络拓扑图

用JTopo在前端绘制网络拓扑图

2.以移动动画效果为例

//创建一个小球沿着线移动var ball = new jtopo.CircleNode(null, 0, 0, 10);
ball.setStyles({
    'fillStyle': 'red',
    'lineWidth': 2
});
layer.addChild(ball);
//Animation.circle表示一个来回
//前两个参数分别表示起点和终点位置
//第三个参数表示从起点到终点的时间,单位是ms
jtopo.Animation.circle(0, 1, 5000, function(t) {
    //随着时间推移不断获取线上的点    
    var p = link3.getPoint(t);
    //将获取的位置赋给小球,达到移动的效果
    ball.text = '' + t.toFixed(1);
    ball.translateCenterTo(p.x, p.y);
}).start().repeat(10); //start表示开始动画,repeat表示重复次数

说明

1.该文章只相当于一个学习笔记,记录了我在项目中使用到的功能和知识点,并没有覆盖JTopo的所有内容。分享出来希望能帮助有类似需求的人快速完成任务。有兴趣可以自己去官网进行深入学习。

2.官网提供了大量demo,并且支持在线修改和运行,非常方便。唯一缺点就是有些注释不够详细,需要不停的试来确定某些方法和参数的意义。我的demo也是参照官网上的demo自己练习时写的,不保证性能。需要完成动画源码的话可以评论或留言。

写在最后

虽然研究生转到了软件,然而进了单位却被分到了系统部门(不是操作系统的系统,是多个设备组成一个系统的系统),常常面对设备控制问题,需要跟硬件对接;再加上软件发展本身就很快,感觉自己什么都不会,永远在学,永远不赶趟,不知道有没有相同经历的朋友