我正在尝试根据节点值分配形状。我的代码类似于:
// some variables from the UI
var anodezoom = d3.select("#nodezoom").property("value");
var asize = d3.select("#ona").property("value");
var acolor = d3.select("#color").property("value");
var ameasure = d3.select("#shape").property("value");
// build, resize, recolor and reshape the nodes
nodes = svg.selectAll('.node')
.data(graph.nodes.filter(function (d) {
return d.degree > 0;
}))
.enter()
.append(function (d) {
shaping(ameasure, d);
})
.attr('class', 'node')
.attr('r', function (d) {
return resizing(anodezoom, asize, d);
})
.style('fill', function (d) {
return coloring(acolor, d);
})
.style('stroke', function (d) {
return coloring(acolor, d);
})
.call(force.drag);
我得到的错误是:
TypeError: Argument 1 ('node') to Node.appendChild must be an instance of Node
发生这种情况是因为我在整形函数中返回一个节点对象失败,即:
function shaping(ashape, anode) {
var shape = null;
if (ashape === "gender") {
if (anode.gender === "M") {
shape = d3.svg.symbolTypes[0];
} else if (anode.gender === "F") {
shape = d3.svg.symbolTypes[1];
} else {
shape = d3.svg.symbolTypes[2];
}
return shape;
};
我基本上会返回一个字符串,这听起来不错,因为它是合法的:
.append('circle')
但是它没有用,所以有没有办法返回一个Node对象,并在shape()函数中分配了正确的形状?
修改
我已将代码更改为:
nodes = svg.selectAll('path')
.data(graph.nodes.filter(function (d) {
return d.degree > 0;
}))
.enter()
.append('path')
.attr('d', d3.svg.symbol().type(function (d) {
return shaping(ashape, d);
}))
.attr('class', 'node')
.attr('r', function (d) {
return resizing(anodezoom, asize, d);
})
.style('fill', function (d) {
return coloring(acolor, d);
})
.style('stroke', function (d) {
return coloring(acolor, d);
})
.call(force.drag);
但是当链接按预期显示时,所有节点都在左上角,几乎看不到......我在这里缺少什么?
答案 0 :(得分:1)
在设置路径数据时,您需要追加路径而不是d3形状,然后指定形状:
.append('path')
.attr('d', function(d) { return d3.symbol().type( /* shape */ ) });
以下是使用形状序数比例(var shape = d3.scaleOrdinal(d3.symbols);
)的简单示例:
.append('path')
.attr("d", d3.symbol().type( function(d) { return shape(d.group);} ) )
它在此block中实现。这个答案是用d3v4,d3v3代码会有点不同。两者的代码在下面的最小示例中进行了比较:
D3V3:
var svg = d3.select('body')
.append('svg');
svg.selectAll('path')
.data(d3.range(6))
.enter()
.append('path')
.attr('transform',function(d,i) { return 'translate('+(i * 30 + 30) + ',20)'; })
.attr('d',d3.svg.symbol()
.type(function(d,i){ return d3.svg.symbolTypes[i]; })
.size(function(d,i){ return i * 30 + 30; })
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
d3v4:
var svg = d3.select('body').append('svg').attr('width',400).attr('height',200);
svg.selectAll('.symbol')
.data(d3.range(6))
.enter()
.append('path')
.attr('transform',function(d,i) { return 'translate('+(i*30+30)+','+30+')';})
.attr('d',d3.symbol()
.type(function(d,i){ return d3.symbols[i];})
.size(function(d,i){ return i * 30 + 30; })
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>