我在这里创建了一个小提琴来复制这个问题:fiddle link
在此之前,我们在项目中使用了一个漂亮的平面json文件。我必须使用的新文件更嵌套。
我的d3功能如下所示:
/* chart data */
// return data for relationships between database tables
returnTableRelationshipData = function(){
var url = 'https://api.myjson.com/bins/7ovnb.json';
d3.json(url, function(data){
//find the node index
function find(f){
var i = -1
data.p.nodes.forEach(function(node, index){
node.x = 200 + Math.random()*200;
node.y = 150 + Math.random()*200;
if(node.properties.nodeID.val == f)
i = index;
});
return i;
}
//set the source and target index
data.p.relationships.forEach(function(d){
d.start = find(d.start);
d.end = find(d.end);
});
// used to store the number of links between two nodes.
var mLinkNum = {};
// sort links first
sortLinks();
// set up linkIndex and linkNumer, because it may possible multiple links share the same source and target node
setLinkIndexAndNum();
// check that we don't have empty or null values
checkDataNotEmpty();
var w = 1000;
var h = 400;
var force = d3.layout.force()
.nodes(data.p.nodes)
.links(data.p.relationships)
.alpha(.1)
.gravity(1)
.charge(-10000)
.size([w, h])
.start();
var svg = d3.select('.node-wrapper').append('svg')
.attr('width', w)
.attr('height', h);
var path = svg.append('svg:g')
.selectAll('path')
.data(force.links())
.enter().append('line')
.attr('class', 'link')
.attr('x1', function(d) {
return d.start.x;
})
.attr('y1', function(d) {
return d.start.y;
})
.attr('x2', function(d) {
return d.end.x;
})
.attr('y2', function(d) {
return d.end.y;
});
var node_drag = d3.behavior.drag()
.on('dragstart', dragstart)
.on('drag', dragmove)
.on('dragend', dragend);
var circle = svg.append('svg:g')
.selectAll('circle')
.data(force.nodes())
.enter().append('svg:circle')
.attr('r', 6)
.call(node_drag);
var text = svg.append('svg:g')
.selectAll('g')
.data(force.nodes())
.enter().append('svg:g');
text.append('svg:text')
.text(function(d){
return d.description;
});
force.on('tick', tick);
function tick() {
path.attr('x1', function(d) {
return d.start.x;
})
.attr('y1', function(d) {
return d.start.y;
})
.attr('x2', function(d) {
return d.end.x;
})
.attr('y2', function(d) {
return d.end.y;
});
circle.attr('transform', function(d){
return 'translate(' + d.x + ',' + d.y + ')';
});
text.attr('transform', function(d){
return 'translate(' + d.x + ',' + d.y + ')';
});
}
function dragstart(d, i) {
force.stop(); // stops the force auto positioning before you start dragging
}
function dragmove(d, i) {
d.px += d3.event.dx;
d.py += d3.event.dy;
d.x += d3.event.dx;
d.y += d3.event.dy;
tick();
}
function dragend(d, i) {
d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
tick();
}
// sort the links by source, then target
function sortLinks(){
if(data.p.relationships != null){
data.p.relationships.sort(function(a,b){
if(a.start > b.start){
return 1;
}else if(a.start < b.start){
return -1;
}else{
if(a.end > b.end){
return 1;
}if(a.end < b.end){
return -1;
}else{
return 0;
}
}
});
}
}
//any links with duplicate source and target get an incremented 'linknum'
function setLinkIndexAndNum(){
for(var i = 0; i < data.p.relationships.length; i++){
if(i != 0 &&
data.p.relationships[i].start == data.p.relationships[i-1].start &&
data.p.relationships[i].end == data.p.relationships[i-1].end){
data.p.relationships[i].linkindex = data.p.relationships[i-1].linkindex + 1;
}else{
data.p.relationships[i].linkindex = 1;
}// save the total number of links between two nodes
if(mLinkNum[data.p.relationships[i].end + ',' + data.p.relationships[i].start] !== undefined){
mLinkNum[data.p.relationships[i].end + ',' + data.p.relationships[i].start] = data.p.relationships[i].linkindex;
}else{
mLinkNum[data.p.relationships[i].start + ',' + data.p.relationships[i].end] = data.p.relationships[i].linkindex;
}
}
}
function checkDataNotEmpty(){
data.p.relationships.forEach(function(link, index, list) {
if (typeof link.start === 'undefined') {
console.log('undefined link', data.p.nodes[link.start]);
}
if (typeof link.end === 'undefined') {
console.log('undefined source', data.p.nodes[link.end]);
}
});
}
});
}();
根据这个answer,如果我注释掉这些行:
var force = d3.layout.force()
//.nodes(data.p.nodes)
//.links(data.p.relationships)
.alpha(.1)
.gravity(1)
...
然后将一个svg对象附加到html。
链接的答案实际上并未提供解决方案。
我唯一的预感是,我不得不将"start"
和"end"
映射到source
和target
,或者我需要转换data.p.nodes
和{{ 1}}不知何故。或者索引可能无法正常工作。
我能够与后端开发人员一起更改一些json属性和类型(字符串,整数等)。
从这里调用json文件:http://myjson.com/7ovnb
答案 0 :(得分:1)
为链接定义笔划以使其可见:
.node-wrapper line {
stroke: #0D9E1E;
}
在.start
函数中将.source
.end
和.target
的所有出现重命名为tick()
。
在find()
函数中,您必须与node.id
属性进行比较:
function find(f){
var i; // do not return an existing value as default
data.p.nodes.forEach(function(node, index){
node.x = 200 + Math.random()*200;
node.y = 150 + Math.random()*200;
if(node.id == f)
i = index;
});
return i;
}
索引0如果是现有节点索引,那么最好不要将其设置为默认值。