我尝试通过d3js可视化网络图 - 以json文件的形式加载它,使用简单的视图函数 - 拖动节点,缩放整个图形和全景图。前两个功能工作正常,但全景...如果我做全图(特别是,当我慢慢地)时 - 所有图片都在颤抖。节点拖动足够顺畅。
这是我的代码:
<html>
<title>dynamic JSON Data</title>
<body id="posts-show">
<header class="post title">
</header>
<style scoped></style>
<style>
svg {
vertical-align: middle;
background: rgba(255,255,255, 0.2);
box-shadow: inset 0 0 3px 0px #CECECE;
}
svg circle {
fill: #AFF;
stroke: steelblue;
stroke-width: 2px;
cursor: pointer;
}
svg line {
stroke-width: 2px;
stroke: #79A32B;
fill: transparent;
cursor: pointer;
}
text {
font: 10px sans-serif;
pointer-events: none;
}
svg circle:active {
stroke: #45D3C7;
fill: #AAA;
}
.action-button {
border-radius: 2px;
border: 1px solid #19380D;
padding: 3px 12px;
background-color: rgba(175, 209, 183, 0.6);
}
.action-button:active {
box-shadow: inset 0 0 3px 0px #868686;
}
.action-button.destroy {
border: 1px solid #863636;
background-color: rgba(197, 86, 86, 0.6);
}
</style>
<script src="d3.js" type="text/javascript"></script>
<script>
var xFn = function(d) { return d.x }
var yFn = function(d) { return d.y }
</script>
<div id="demo" style="text-align: center;">
</div>
<script>
d3.json("Graph_source.json", function(json) {
var zoom = d3.behavior.zoom()
.scaleExtent([-5, 20])
.on("zoom", zoomed);
function zoomed() {
g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
};
function dragstarted(d) {
d3.event.sourceEvent.stopPropagation();
d3.select(this).classed("dragging", true);
};
function dragended(d) {
d3.select(this).classed("dragging", false);
};
var canvas_size = json['canvas'];
var nodes_list = json['nodes'];
var links_list = json['edges'];
var width = canvas_size[0].width;
var height = canvas_size[0].height;
var drag2 = d3.behavior.drag()
.origin(function(d) { return d; })
.on("dragstart", dragstarted)
.on('drag', function (d,i) {
g.attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
console.log(d.id + ";" + d.x + ";" + d.y + ";")
})
.on("dragend", dragended);
var svg = d3.select("#demo").append("svg")
.attr("width", width)
.attr("height", height)
var g = svg.append("g")
.attr("transform", "translate(" + 0 + "," + 0 + ")")
.call(zoom)
.call(drag2);
var rect = g.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all");
/* Define the data for the circles */
var nodes = g.selectAll("g")
.data(nodes_list)
/* Define the data for the lines */
var links = g.selectAll("link").data(links_list)
/* var xScale = d3.scale.linear()
.range([50, 750])
.domain(d3.extent(nodes_list, xFn));
var yScale = d3.scale.linear()
.range([50, 550])
.domain(d3.extent(nodes_list, yFn));*/
var drag = d3.behavior.drag()
.origin(function(d) { return d; })
.on("dragstart", dragstarted)
.on('drag', function (d,i) {
d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
console.log(d.id + ";" + d.x + ";" + d.y + ";")
d3.select(this).attr("transform", function (d, i) {
return "translate(" + [d.x,d.y] + ")";
})
links
.attr("x1", function(d) { return get_node_x(d.source); })
.attr("y1", function(d) { return get_node_y(d.source); })
.attr("x2", function(d) { return get_node_x(d.target); })
.attr("y2", function(d) { return get_node_y(d.target); });
})
.on("dragend", dragended);
function get_node_x(search_key)
{
for (var i = 0; i < nodes_list.length; i++)
{
if(search_key.localeCompare(nodes_list[i].id) == 0)
{
return nodes_list[i].x;
}
}
};
function get_node_y(search_key)
{
for (var i = 0; i < nodes_list.length; i++)
{
if(search_key.localeCompare(nodes_list[i].id) == 0)
{
return nodes_list[i].y;
}
}
};
links.enter()
.append("line")
.attr("class", "link")
.attr("x1", function(d) { return get_node_x(d.source); })
.attr("y1", function(d) { return get_node_y(d.source); })
.attr("x2", function(d) { return get_node_x(d.target); })
.attr("y2", function(d) { return get_node_y(d.target); });
/*Create and place the "blocks" containing the circle and the text */
var elemEnter = nodes.enter()
.append("g")
.attr("transform", function(d){return "translate("+ d.x +","+ d.y +")"})
.on("mouseover", function(d) {
console.log(d.id + ";" + d.x + ";" + d.x + ";" + d3.event.dx + ";" + d.y + ";" + d.y + ";" + d3.event.dy + ";")
})
.call(drag);
/*Create the circle for each block */
var circle = elemEnter.append("circle")
.attr("r", 10)
/* Create the text for each block */
elemEnter.append("text")
.attr("text-anchor", "middle")
.text(function(d){return d.label});
console.log(json);
console.log(svg);
});
</script>
</body>
</html>
和源文件Graph_source.json:
{
"canvas":[
{"width": 721, "height": 352}
],
"nodes":[
{"id": "MPLS-BH-01", "label": "MPLS-BH-01" , "Host_IP": "10.158.20.3" , "size": "10.0" , "r": "153" , "g": "153" , "b": "153" , "x": 396 , "y": 60 },
{"id": "MPLS-BH-02", "label": "BH-02" , "Host_IP": "10.158.20.6" , "size": "10.0" , "r": "153" , "g": "153" , "b": "153" , "x": 192 , "y": 292 },
{"id": "MPLS-BH-03", "label": "BH-03" , "Host_IP": "10.158.20.4" , "size": "10.0" , "r": "153" , "g": "153" , "b": "153" , "x": 601 , "y": 93 },
{"id": "MPLS-BH-04", "label": "BH-04" , "Host_IP": "10.158.20.5" , "size": "10.0" , "r": "153" , "g": "153" , "b": "153" , "x": 333 , "y": 291 },
{"id": "MPLS-BH-05", "label": "BH-05" , "Host_IP": "10.158.20.1" , "size": "10.0" , "r": "153" , "g": "153" , "b": "153" , "x": 121 , "y": 191 },
{"id": "MPLS-BH-06", "label": "BH-06" , "Host_IP": "10.158.20.2" , "size": "10.0" , "r": "153" , "g": "153" , "b": "153" , "x": 241 , "y": 67 }
],
"edges":[
{"source": "MPLS-BH-02", "target": "MPLS-BH-04", "weight": "1.0" , "Host_A": "MPLS-BH-02" , "Interface_A": "GigabitEthernet1/2/0" , "Host_B": "MPLS-BH-04" , "Interface_B": "GigabitEthernet1/2/1" , "BW": "100" },
{"source": "MPLS-BH-03", "target": "MPLS-BH-04", "weight": "1.0" , "Host_A": "MPLS-BH-03" , "Interface_A": "GigabitEthernet1/2/1" , "Host_B": "MPLS-BH-04" , "Interface_B": "GigabitEthernet1/2/0" , "BW": "100" },
{"source": "MPLS-BH-05", "target": "MPLS-BH-06", "weight": "1.0" , "Host_A": "MPLS-BH-05" , "Interface_A": "GigabitEthernet2/0/0" , "Host_B": "MPLS-BH-06" , "Interface_B": "GigabitEthernet2/0/0" , "BW": "100" }
]
}
答案 0 :(得分:1)
在包含的组元素上调用缩放,但实际上会转换包含的组元素。
var gContainer = svg.append("g");
.attr("transform", "translate(" + 0 + "," + 0 + ")")
.call(zoom)
var g = gContainer.append("g")
// the following stays the same
function zoomed() {
g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
};
答案 1 :(得分:0)
我花了大约两天时间来解决摇晃问题。请参阅Plunker。 http://plnkr.co/edit/D6JU88?p=preview
<html>
<title>dynamic JSON Data</title>
<body id="posts-show">
<header class="post title">
</header>
<style scoped></style>
<style>
svg {
vertical-align: middle;
background: rgba(255,255,255, 0.2);
box-shadow: inset 0 0 3px 0px #CECECE;
}
svg circle {
fill: #AFF;
stroke: steelblue;
stroke-width: 2px;
cursor: pointer;
}
svg line {
stroke-width: 2px;
stroke: #79A32B;
fill: transparent;
cursor: pointer;
}
text {
font: 10px sans-serif;
pointer-events: none;
}
svg circle:active {
stroke: #45D3C7;
fill: #AAA;
}
.action-button {
border-radius: 2px;
border: 1px solid #19380D;
padding: 3px 12px;
background-color: rgba(175, 209, 183, 0.6);
}
.action-button:active {
box-shadow: inset 0 0 3px 0px #868686;
}
.action-button.destroy {
border: 1px solid #863636;
background-color: rgba(197, 86, 86, 0.6);
}
</style>
<script src="http://d3js.org/d3.v3.js"></script>
<script>
var xFn = function(d) { return d.x }
var yFn = function(d) { return d.y }
</script>
<div id="demo" style="text-align: center;">
</div>
<script>
d3.json("Graph_source.json", function(json) {
var canvas_size = json['canvas'];
var nodes_list = json['nodes'];
var links_list = json['edges'];
var width = canvas_size[0].width;
var height = canvas_size[0].height;
var zoom = d3.behavior.zoom()
.scaleExtent([-5, 20])
.size([width,height])
.on("zoom", zoomed);
function zoomed() {
container.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
};
function dragstarted(d) {
d3.event.sourceEvent.stopPropagation();
// d3.select(this).classed("dragging", true);
};
function dragended(d) {
// d3.select(this).classed("dragging", false);
};
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + 0 + "," + 0 + ")")
.call(zoom);
var rect = svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all");
var container = svg.append("g");
/* Define the data for the circles */
var nodes = container.selectAll("g")
.data(nodes_list)
/* Define the data for the lines */
var links = container.selectAll("link").data(links_list)
/* var xScale = d3.scale.linear()
.range([50, 750])
.domain(d3.extent(nodes_list, xFn));
var yScale = d3.scale.linear()
.range([50, 550])
.domain(d3.extent(nodes_list, yFn));*/
var drag = d3.behavior.drag()
.origin(function(d) { return d; })
.on("dragstart", dragstarted)
.on('drag', function (d,i) {
d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
console.log(d.id + ";" + d.x + ";" + d.y + ";")
d3.select(this).attr("transform", function (d, i) {
return "translate(" + [d.x,d.y] + ")";
})
links
.attr("x1", function(d) { return get_node_x(d.source); })
.attr("y1", function(d) { return get_node_y(d.source); })
.attr("x2", function(d) { return get_node_x(d.target); })
.attr("y2", function(d) { return get_node_y(d.target); });
})
.on("dragend", dragended);
function get_node_x(search_key)
{
for (var i = 0; i < nodes_list.length; i++)
{
if(search_key.localeCompare(nodes_list[i].id) == 0)
{
return nodes_list[i].x;
}
}
};
function get_node_y(search_key)
{
for (var i = 0; i < nodes_list.length; i++)
{
if(search_key.localeCompare(nodes_list[i].id) == 0)
{
return nodes_list[i].y;
}
}
};
links.enter()
.append("line")
.attr("class", "link")
.attr("x1", function(d) { return get_node_x(d.source); })
.attr("y1", function(d) { return get_node_y(d.source); })
.attr("x2", function(d) { return get_node_x(d.target); })
.attr("y2", function(d) { return get_node_y(d.target); });
/*Create and place the "blocks" containing the circle and the text */
var elemEnter = nodes.enter()
.append("g")
.attr("transform", function(d){return "translate("+ d.x +","+ d.y +")"})
.on("mouseover", function(d) {
console.log(d.id + ";" + d.x + ";" + d.x + ";" + d3.event.dx + ";" + d.y + ";" + d.y + ";" + d3.event.dy + ";")
})
.call(drag);
/*Create the circle for each block */
var circle = elemEnter.append("circle")
.attr("r", 10)
/* Create the text for each block */
elemEnter.append("text")
.attr("text-anchor", "middle")
.text(function(d){return d.label});
console.log(json);
console.log(svg);
}
);
</script>
</body>
</html>