我正在寻找要在 D3JS 中实现的算法或布局,以呈现“一般”格的图形,即不是(必然)二项式的格。
我想获得的结果的一个例子是:
我想将晶格可视化为从底部到顶部的层次结构,类似于树状结构。
我尝试调整强制布局,但效果不佳,尤其是因为很难正确定位层次结构的级别。
我对输入的形式没有任何限制,它可能更适合该过程。
我正在寻找要在 D3JS 中实现的算法或布局,以呈现“一般”格的图形,即不是(必然)二项式的格。
我想获得的结果的一个例子是:
我想将晶格可视化为从底部到顶部的层次结构,类似于树状结构。
我尝试调整强制布局,但效果不佳,尤其是因为很难正确定位层次结构的级别。
我对输入的形式没有任何限制,它可能更适合该过程。
你可以做这样的事情,但我不确定它会有多大用处。它利用了cola.js
图书馆。
// Sample data set
var json = {
nodes: [
{ "name": 'Beverage' },
{ "name": 'nonAlcoholic' },
{ "name": 'sparkling' },
{ "name": 'alcoholic' },
{ "name": 'hot' },
{ "name": 'caffeinic' },
{ "name": 'MineralWater' },
{ "name": 'madeFromGrain' },
{ "name": 'madeFromGrapes' },
{ "name": 'HerbTea' },
{ "name": 'Coffee' },
{ "name": 'Cola' },
{ "name": 'Beer' },
{ "name": 'Wine' },
{ "name": 'Champagne' },
{ "name": '' }
],
links: [
{ "source": 0, "target": 1},
{ "source": 0, "target": 2},
{ "source": 0, "target": 3},
{ "source": 1, "target": 4},
{ "source": 1, "target": 5},
{ "source": 1, "target": 6},
{ "source": 2, "target": 6},
{ "source": 2, "target": 7},
{ "source": 2, "target": 14},
{ "source": 3, "target": 7},
{ "source": 3, "target": 8},
{ "source": 4, "target": 9},
{ "source": 4, "target": 10},
{ "source": 5, "target": 10},
{ "source": 5, "target": 11},
{ "source": 6, "target": 11},
{ "source": 7, "target": 12},
{ "source": 8, "target": 13},
{ "source": 8, "target": 13},
{ "source": 13, "target": 14},
{ "source": 10, "target": 15},
{ "source": 11, "target": 15},
{ "source": 12, "target": 15},
{ "source": 14, "target": 15},
]
};
var width = 800, height = 600, n = 10000;
var svg = d3.select('#vis').append('svg').attr('width', width).attr('height', height);
var force = cola.d3adaptor()
.linkDistance(80)
.size([width, height])
.nodes(json.nodes)
.links(json.links)
.flowLayout("y", 25)
.on("tick", tick)
.start();
var node = svg.selectAll("circle.node")
.data(json.nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", 5);
var text = svg.selectAll("text.label")
.data(json.nodes)
.enter().append("text")
.attr("class", "label")
.text(function(d) { return d.name; });
var link = svg.selectAll("line.link")
.data(json.links)
.enter().append("line")
.attr("class", "link");
function tick() {
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; });
text.attr("x", function(d) { return d.x + 8; })
.attr("y", function(d) { return d.y; });
}
function hover(d) {
switch(d3.event.type) {
case "mouseover": var tip = svg.append("g")
.attr("class", "tip")
.attr("transform", "translate(" + d3.event.x + "," + d3.event.y + ")");
var rect = tip.append("rect")
.attr("fill", "white");
var text = tip.append("text")
.text(d.name);
var bounds = text.node().getBBox();
rect.attr("x", bounds.x)
.attr("y", bounds.y)
.attr("width", bounds.width)
.attr("height", bounds.height);
break;
case "mouseout": svg.selectAll("g.tip")
.remove();
break;
default: break;
}
}
text {
font: 10px sans-serif;
}
line {
stroke: #000;
stroke-width: 1.5px;
}
circle {
stroke: #fff;
stroke-width: 1.5px;
}
<div id="vis"></div>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="http://marvl.infotech.monash.edu/webcola/cola.v3.min.js"></script>
使用cola.js
您可以指定其他约束以帮助正确布局。就目前而言,我对其施加的唯一约束是flowLayout
参数。这样做的好处是布局是可重复的,并且使用d3
强制布局实现类似的结果可能非常困难(尽管公平地说,它并不是真的打算以这种方式使用)。
我不会声称这是一个很好的结果,但是由于没有手动确定节点位置或接受标准的d3
力布局,这可能是获得接近您所追求的东西的最简单和最快捷的方法之一。
编辑:显示如何使用悬停。
// Sample data set
var json = {
nodes: [
{ "name": 'Beverage' },
{ "name": 'nonAlcoholic' },
{ "name": 'sparkling' },
{ "name": 'alcoholic' },
{ "name": 'hot' },
{ "name": 'caffeinic' },
{ "name": 'MineralWater' },
{ "name": 'madeFromGrain' },
{ "name": 'madeFromGrapes' },
{ "name": 'HerbTea' },
{ "name": 'Coffee' },
{ "name": 'Cola' },
{ "name": 'Beer' },
{ "name": 'Wine' },
{ "name": 'Champagne' },
{ "name": '' }
],
links: [
{ "source": 0, "target": 1},
{ "source": 0, "target": 2},
{ "source": 0, "target": 3},
{ "source": 1, "target": 4},
{ "source": 1, "target": 5},
{ "source": 1, "target": 6},
{ "source": 2, "target": 6},
{ "source": 2, "target": 7},
{ "source": 2, "target": 14},
{ "source": 3, "target": 7},
{ "source": 3, "target": 8},
{ "source": 4, "target": 9},
{ "source": 4, "target": 10},
{ "source": 5, "target": 10},
{ "source": 5, "target": 11},
{ "source": 6, "target": 11},
{ "source": 7, "target": 12},
{ "source": 8, "target": 13},
{ "source": 8, "target": 13},
{ "source": 13, "target": 14},
{ "source": 10, "target": 15},
{ "source": 11, "target": 15},
{ "source": 12, "target": 15},
{ "source": 14, "target": 15},
]
};
var width = 800, height = 600, n = 10000;
var svg = d3.select('#vis').append('svg').attr('width', width).attr('height', height);
var force = cola.d3adaptor()
.linkDistance(80)
.size([width, height])
.nodes(json.nodes)
.links(json.links)
.flowLayout("y", 25)
.on("tick", tick)
.start();
var link = svg.selectAll("line.link")
.data(json.links)
.enter().append("line")
.attr("class", "link");
var node = svg.selectAll("circle.node")
.data(json.nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", 10)
.on("mouseover", hover)
.on("mouseout", hover);
function tick() {
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; });
}
function hover(d) {
switch(d3.event.type) {
case "mouseover":
console.log(d3.event);
var tip = svg.append("g")
.attr("class", "tip")
.attr("transform", "translate(" + d3.event.clientX + "," + d3.event.clientY + ")");
var rect = tip.append("rect")
.attr("fill", "white");
var text = tip.append("text")
.text(d.name);
var bounds = text.node().getBBox();
rect.attr("x", bounds.x)
.attr("y", bounds.y)
.attr("width", bounds.width)
.attr("height", bounds.height);
break;
case "mouseout": svg.selectAll("g.tip")
.remove();
break;
default: break;
}
}
text {
font: 10px sans-serif;
}
line {
stroke: #000;
stroke-width: 1.5px;
}
circle {
stroke: #fff;
stroke-width: 1.5px;
}
<div id="vis"></div>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="http://marvl.infotech.monash.edu/webcola/cola.v3.min.js"></script>