canvas版的拓扑图(topo)展示工具.
总在使用别人的开源插件来绘制拓扑,总是不能满足公司各个项目的各种需求,痛定思痛自己搞一套吧.
ps: 感谢UI设计师yoki对topo图做的UI设计,很赞!!!
ps: 因为ff,chrome不支持本地请求json文件, 将整体工程放到本服务器下运行最为适宜.
(1)适用于监控网络ip节点互联关系的场景
(2)适用于社交网络的群组互联访问关系
ie9+,firefox,chrome,safari.
300+节点毫无压力,顺畅的没有朋友,正常使用尽量控制在300左右.
节点的碰撞检测5千节点1ms左右,连线的碰撞检测5千连线1ms左右,(ff,chrome一样)
如果需要展示上千节点请参考以下调优方案
调优方案参考
(1)将力导向布局的迭代次数从300次下降到150次,布局时间缩小一倍,例:10s---优化后5s
(2)将布局算法放在后台执行,将前台布局设置为[预设],按java举例,例:10s---优化后2s
(3)将节点的显示标签Label隐藏,下面列举了绘制label的性能影响,例:10s---优化后3s
(4)用空间换时间,将坐标保留,不用每次draw都要重新计算布局
ps: 绘制节点标签还是挺吃性能的
绘制节点不带label
//ff (浏览器卡死, 建议使用服务器端计算)
//chrome nodes count=1000,edges count=1000,layout time=4838,draw time=9
//ff nodes count=500,edges count=500,layout time=9543,draw time=19
//chrome nodes count=500,edges count=500,layout time=1272,draw time=6
//ff nodes count=300,edges count=300,layout time=3445,draw time=11
//chrome nodes count=300,edges count=300,layout time=475,draw time=4
//ff nodes count=200,edges count=200,layout time=1551,draw time=7
//chrome nodes count=200,edges count=200,layout time=233,draw time=4
绘制节点带label
//ff (浏览器卡死, 建议使用服务器端计算)
//chrome nodes count=1000,edges count=1000,layout time=4838,draw time=39
//ff nodes count=500,edges count=500,layout time=9543,draw time=125
//chrome nodes count=500,edges count=500,layout time=1272,draw time=23
//ff nodes count=300,edges count=300,layout time=3445,draw time=77
//chrome nodes count=300,edges count=300,layout time=475,draw time=16
//ff nodes count=200,edges count=200,layout time=1551,draw time=49
//chrome nodes count=200,edges count=200,layout time=233,draw time=10
(1)力导向布局算法性能差一点,还需要进一步优化
(2)不支持节点图片和图标
(3)不支持框选操作
(1)提供控制面板;
(2)支持鼠标滑轮和拖拽的放大,缩小;
(3)上下左右键盘平移;
(4)拖拽单个节点和屏幕;
(5)支持点击和悬停节点;
(6)支持点击和悬停连线;
(7)支持悬停节点的关联节点高亮;
(8)提供事件回调接口;
(9)支持连线箭头;
(10)支持连线的流动动画;
(11)支持力导向布局定位,即每次刷新页面,坐标不变;
(1)使用html5的canvas标签来实现的;
(2)布局算法使用力导向布局(库仑斥力公式和胡克定律公式)来自网络;
(3)节点的碰撞检测使用勾股定理测距;
(4)连线的碰撞检测使用反正切计算夹角;
MIT(随意使用,免费开源)
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="text/javascript" src="ctopo.js"></script>
<script type="text/javascript">
//调用ctopo
ctopo({
id:"canvas", //说明: canvas标签的id, 写法: canvas , #canvas
width:"auto", //说明: canvas的宽度, 写法: 500,500px,50%,auto
height:"auto", //说明: canvas的高度, 写法: 500,500px,50%,auto
style:{ //说明: 样式省略了.....
global:{},
node:{},
edge:{}
},
layout:{}, //说明: 布局省略了.....
data:{}, //说明: 数据省略了.....
event:{} //说明: 事件回调省略了.....
});
</script>
</body>
</html>
//取得ctopo对象, 点出api方法即可
var ctopo = ctopo({..各种基础配置..});
var nodeA = ctopo.node("1108"); //获取节点A
var nodeB = ctopo.node("0724"); //获取节点B
var edge = ctopo.edge("1108","0724"); //获取连线
属性名 | 描述 |
version | 版本 |
option | 配置对象 |
canvas | 画布对象 |
context | 画布上下文对象 |
nodes | 节点数组 |
edges | 连线对象 |
方法名 | 描述 | 参数 | 返回值 |
addEdge(edge,isDrawNow) | 添加连线 |
参数1: edge添加的连线对象 参数2: isDrawNow是否立刻渲染到屏幕 |
空 |
addNode(node,isDrawNow) | 添加节点 |
参数1: edge添加的节点对象 参数2: isDrawNow是否立刻渲染到屏幕 |
空 |
draw(option) | 重新绘制画布, 用法等于ctopo(option) |
参数1: option初始的配置对象 |
空 |
drawData(data,isApplyLayout) | 局部刷新,只刷新数据 |
参数1: data格式=optioin.data 参数2: isApplyLayout是否重新应用布局 |
成功true,失败false |
edge(sid,tid) |
取得连线对象 ps:区分方向 |
参数1: 开始节点id 参数2: 结束节点id |
查到: 连线对象 没查到: null |
edgeArray() | 取得所有的连线对象数组 | 无 | 连线对象数组 |
firstNeighbors(nid) | 返回与之关联的连线和节点数组对象 |
参数1: nid待匹配的节点id |
查到:关联数据对象; 没查到:空数组对象 { edgeNeighbors:[], nodeNeighbors:[] } |
layout(layout) | 重置切换布局 |
(可选)参数1: layout==option.layout |
无参数: 返回option.layout 有参数: 重置布局, 成功true,失败false |
node(id) | 取得节点对象 |
参数1: 节点id |
查到:节点对象 没查到:null |
nodeLabelsVisible(visible) | 设置节点标签是否显示 |
参数1: visible是否显示标签, 布尔型true,false |
空 |
edgeLabelsVisible(visible) | 设置连线标签是否显示 |
参数1: visible是否显示标签, 布尔型true,false |
空 |
edgeArrowsVisible(visible) | 设置连线箭头是否显示 |
参数1: visible是否显示箭头, 布尔型true,false |
空 |
nodeArray() | 取得所有节点对象数组 | 无 | 节点对象数组 |
nodeTooltipsVisible(visible) | 设置节点提示框是否显示 |
参数1: visible是否显示提示框, 布尔型true,false |
空 |
edgeTooltipsVisible(visible) | 设置连线提示框是否显示 |
参数1: visible是否显示提示框, 布尔型true,false |
空 |
edgeAnimateBallsVisible(visible) | 设置连线动画球是否显示 |
参数1: visible是否显示动画球, 布尔型true,false |
空 |
consolePanelVisible(visible) | 设置控制台是否显示 |
参数1: visible是否显示控制台, 布尔型true,false |
空 |
removeEdge(sid,tid,isDrawNow) | 删除连线 |
参数1: 开始节点id 参数2: 结束节点id 参数3: 是否立刻渲染到屏幕 |
空 |
removeNode(id,isDrawNow) | 删除节点,与之关联的线也删除 |
参数1: 节点id 参数2: 是否立刻渲染到屏幕 |
空 |
updateEdge(edge,isDrawNow) | 更新连线 |
参数1: 连线对象 参数3: 是否立刻渲染到屏幕 |
空 |
updateNode(node,isDrawNow) | 更新节点 |
参数1: 节点对象 参数2: 是否立刻渲染到屏幕 |
空 |
style(style) | 重置切换样式 |
(可选)参数1: style==option.style |
无参数: 返回option.style 有参数: 重置样式, 成功true,失败false |
zoom(scale) | 设置缩放比例(0-1) |
(可选)参数1: scale比例0-1,100%=0.5 |
无参数: 返回比例值 有参数: 设置比例值, 成功ture,失败false |