我正在使用 d3.js 和 jquery 以及 PHP 后端(基于 yii 框架)来创建一个动态的力有向图来表示我们使用 Nagios 监控的网络上主机和服务的当前状态。
该图显示根 -> 主机组 -> 主机 -> 服务。我创建了一个服务器端函数以返回以下格式的 JSON 对象
{
"nodes": [
{
"name": "MaaS",
"object_id": 0
},
{
"name": "Convergence",
"object_id": "531",
"colour": "#999900"
},
{
"name": "maas-servers",
"object_id": "719",
"colour": "#999900"
},
{
"name": "hrg-cube",
"object_id": "400",
"colour": "#660033"
}
],
"links": [
{
"source": 0,
"target": "531"
},
{
"source": 0,
"target": "719"
},
{
"source": "719",
"target": "400"
}
]
}
节点包含在链接中使用的对象 ID,以及用于显示节点状态的颜色(OK = 绿色,WARNING = 黄色等)链接具有节点的源对象 ID 和目标对象 ID。随着从监控系统中添加或删除新主机,节点和链接可能会发生变化
我有以下代码设置初始 SVG,然后每 10 秒
- 检索当前 JSON 对象
- 创建链接地图
- 选择当前节点和链接并将它们绑定到 JSON 数据
- 添加进入链接并删除退出链接
- 更新和添加的节点将更改其填充颜色,并添加一个带有名称的工具提示
强制开始
$.ajaxSetup({ 缓存: false }); 宽度 = 960,高度 = 500;节点 = []; 链接 = []; force = d3.layout.force() .charge(-1000) .linkDistance(1) .size([width, height]);
svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height) .append("g"); setInterval(function(){ $.ajax({ url: "<?php echo $url;?>", type: "post", async: false, datatype: "json", success: function(json, textStatus, XMLHttpRequest) { json = $.parseJSON(json); var nodeMap = {}; json.nodes.forEach(function(x) { nodeMap[x.object_id] = x; }); json.links = json.links.map(function(x) { return { source: nodeMap[x.source], target: nodeMap[x.target], }; }); link = svg.selectAll("line") .data(json.links); node = svg.selectAll("circle") .data(json.nodes,function(d){return d.object_id}) link.enter().append("line").attr("stroke-width",1).attr('stroke','#999'); link.exit().remove(); node.enter().append("circle").attr("r",5); node.exit().remove(); node.attr("fill",function(d){return d.colour}); node.append("title") .text(function(d) { return d.name; }); node.call(force.drag); force .nodes(node.data()) .links(link.data()) .start() force.on("tick", function() { link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("cx", function(d) { return d.x = Math.max(5, Math.min(width - 5, d.x)); }) .attr("cy", function(d) { return d.y = Math.max(5, Math.min(height - 5, d.y)); }); }); } }); },10000);
可以在网络可视化中看到输出示例
上述所有操作都正常工作,但每次代码循环时都会导致可视化重新启动,并且节点都会反弹,直到它们稳定下来。我需要的是让任何当前项目保持原样,但任何新节点和链接都将添加到可视化中,并且可以单击和拖动等。
如果有人可以提供帮助,我将永远感激不尽。