我有一个强制定向布局。节点派生自json值,其具有名称,组作为节点,源,目标和值作为链接。 json可以带有价值'尺寸'作为节点的一部分,我想看看我是否可以使用这个值来确定节点的放置位置0这个想法是尺寸越大,画布上放置的越高。
我有两个问题。 a)如果json在需要的基础上携带额外的元素,我不知道d3.js是否会渲染; b)我不确定如何根据这个' size'来更改y属性。元件。
我试过的代码是:
var width = 1400,
height = 500
var color = d3.scale.category20();
var force = d3.layout.force()
.charge(-100)
.linkDistance(130)
.size([width, height]);
var svg = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.call(d3.behavior.zoom().scaleExtent([1, 8]).on("zoom", zoom))
.append("g");
function zoom() {
svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
var endpoint = window.location.href+".json"
d3.json(endpoint, function(graph) {
force
.nodes(graph.nodes)
.links(graph.links)
.start();
var link = svg.selectAll(".link")
.data(graph.links)
.enter().append("line")
.attr("class", "link")
.style("marker-end", "url(#suit)");
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", function(d) { return d.group * 3; })
.attr("cy", function(d) { return d.group; })
.style("fill", function(d) { return color(d.group); })
.call(force.drag)
.on('mouseover', connectedNodes)
.on('mouseout', UnconnectedNodes)
.on("click", function(d) { getprofile2(d); });
function getprofile2(d){
$.ajax({
url: "/graph/show",
type: "GET",
dataType: 'html',
data: {name: d.name},
success: function(result) {
$('.bchart-content').html(result);
addGraph(result);
}
});
}
node.append("title")
.text(function(d) { return d.name; });
node.append("circle")
.attr("r", function(d) { return d.group * 3; });
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; })
.attr("cy", function(d) { return d.y; });
});
//Toggle stores whether the highlighting is on
var toggle = 0;
//Create an array logging what is connected to what
var linkedByIndex = {};
for (i = 0; i < graph.nodes.length; i++) {
linkedByIndex[i + "," + i] = 1;
};
graph.links.forEach(function (d) {
linkedByIndex[d.source.index + "," + d.target.index] = 1;
});
//This function looks up whether a pair are neighbours
function neighboring(a, b) {
return linkedByIndex[a.index + "," + b.index];
}
function connectedNodes() {
if (toggle == 0) {
//Reduce the opacity of all but the neighbouring nodes
d = d3.select(this).node().__data__;
node.style("opacity", function (o) {
return neighboring(d, o) | neighboring(o, d) ? 1 : 0.1;
});
link.style("opacity", function (o) {
return d.index==o.source.index | d.index==o.target.index ? 1 : 0.1;
});
//Reduce the op
toggle = 1;
} else {
//Put them back to opacity=1
node.style("opacity", 1);
link.style("opacity", 1);
toggle = 0;
}
}
function UnconnectedNodes() {
node.style("opacity", 1);
link.style("opacity", 1);
toggle = 0;
}
graphRec=JSON.parse(JSON.stringify(graph));
function threshold(thresh) {
graph.links.splice(0, graph.links.length);
for (var i = 0; i < graphRec.links.length; i++) {
if (graphRec.links[i].value > thresh) {graph.links.push(graphRec.links[i]);}
}
restart();
}
//Restart the visualisation after any node and link changes
function restart() {
link = link.data(graph.links);
link.exit().remove();
link.enter().insert("line", ".node").attr("class", "link");
node = node.data(graph.nodes);
node.enter().insert("circle", ".cursor").attr("class", "node").attr("r", 5).call(force.drag);
force.start();
}
});
但没有任何改变。
我的数据如下:
{
"nodes":[
{
"name":"Et",
"group":5
"size":14
},
{
"name":"Non Qui",
"group":5,
"size":19
},
{
"name":"Officiis",
"group":1
"size":13
},
{
"name":"Bilbo",
"group":1
"size":10
}
],
"links":[
{
"source":1,
"target":2,
"value":2
},
{
"source":1,
"target":3,
"value":1
}
]
}
答案 0 :(得分:2)
Here是一个如何调整引力函数以产生你所追求的效果的例子。我还添加了一些震动以帮助扩散...
var width = 960,
height = 500,
padding = 0, // separation between nodes
maxRadius = 12;
var n = 1000, // total number of nodes
m = 10; // number of distinct layers
var color = d3.scale.category10()
.domain(d3.range(m));
var y = d3.scale.ordinal()
.domain(d3.range(m))
.rangePoints([height, 0], 1);
var nodes = d3.range(n).map(function() {
var i = Math.floor(Math.random() * m),
v = (i + 10) / m * -Math.log(Math.random());
return {
radius: Math.sqrt(v) * maxRadius,
color: color(i),
cy: y(i)
};
});
var force = d3.layout.force()
.nodes(nodes)
.size([width, height])
.gravity(0)
.charge(0)
.on("tick", tick)
.start();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var circle = svg.selectAll("circle")
.data(nodes)
.enter().append("circle")
.attr("r", function(d) {
return d.radius;
})
.style("fill", function(d) {
return d.color;
})
.call(force.drag);
function tick(e) {
var a = e.alpha;
circle
.each(gravity(.2 * a))
.each(collide(.5))
.attr("cx", function(d) {
return brownian(d.x, a);
})
.attr("cy", function(d) {
return brownian(d.y, a);
});
force.alpha(a / 0.99 * 0.999)
}
var brownian = (function(w) {
return function(x, a) {
return x + (Math.random() - 0.5) * w * a
}
})(10);
// Move nodes toward cluster focus.
function gravity(alpha) {
return function(d) {
d.y += (d.cy - d.y) * alpha;
// d.x += (d.cx - d.x) * alpha;
};
}
// Resolve collisions between nodes.
function collide(alpha) {
var quadtree = d3.geom.quadtree(nodes);
return function(d) {
var r = d.radius + maxRadius + padding,
nx1 = d.x - r,
nx2 = d.x + r,
ny1 = d.y - r,
ny2 = d.y + r;
quadtree.visit(function(quad, x1, y1, x2, y2) {
if (quad.point && (quad.point !== d)) {
var x = d.x - quad.point.x,
y = d.y - quad.point.y,
l = Math.sqrt(x * x + y * y),
r = d.radius + quad.point.radius + (d.color !== quad.point.color) * padding;
if (l < r) {
l = (l - r) / l * alpha;
d.x -= x *= l;
d.y -= y *= l;
quad.point.x += x;
quad.point.y += y;
}
}
return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
});
};
}
&#13;
circle {
stroke: #fff;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
答案 1 :(得分:0)
根据您的数据,代码应如下所示:
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", function(d) { return d.group * 3; })
.attr("cy", function(d) { return d.size; })
.style("fill", function(d) { return color(d.group); })
实际的&#34; cy&#34;也可能取决于绘图区域的最大高度,因此您可能需要相应地缩放它。
希望这会有所帮助:)