我正在用小圆子弹绘制线条图。但是,数据中有漏洞,在我的数组中由null表示。当然,只要没有数据,就不应该有圈子。但是d3的append()方法无论如何都会添加它们。我该如何避免这种情况?
这是jsFiddle mockup完全重现我的问题。
我感兴趣的是没有那个系列的圆圈位于我的图形的X轴上,因为它们都是空的。
来自jsfiddle链接的相关代码:
svg.selectAll('circle').data(values).enter()
.append('circle')// <-- I don't want to do this for null's
.attr('fill', '#c00')
.attr('r', 3)
.attr('cx', xi)
.attr('cy', yFlipped)
答案 0 :(得分:28)
一种选择是以不同方式表示您的数据,以便您不依赖于索引来计算x坐标。例如,如果您将每个数据表示为对象(例如{x: 0, y: 0.2840042}
),那么您可以将x坐标计算为x(d.x)
而不是x(i)
。
另一个选项是当值为null时将半径设置为零,因此隐藏了圆圈:circle.attr("r", function(d) { return d == null ? 0 : 3; })
。或者,您可以隐藏圈子:circle.style("display", function(d) { return d == null ? "none" : null; })
。
您还可以在追加空元素后删除它们:circle.filter(function(d) { return d == null; }).remove()
。这适用于初始创建,但我不推荐它,因为如果您稍后重新选择元素,索引将会改变。
答案 1 :(得分:2)
最简单的选择是从传递给.data(…)
的数据中过滤掉空值,增加数据以维护索引:
svg.selectAll('circle')
.data(values
.map(function(v, idx) { return v == null? null : { idx: idx, value: v })
.filter(function(v) { return v != null })
)
.enter()
.append('circle')
.attr('fill', '#c00')
.attr('r', 3)
.attr('cx', function(d) { return d.idx * 10 }) // or whatever
.attr('cy', function(d) { return d.value.y }) // or whatever
请注意,即使它们不是自然列表,您也可以遵循此模式的各个子元素。例如,考虑一种您希望有条件地添加第二个圆圈的情况:
var circles = [
{ color: 'red', cx: 30, cy: 30, subCircleColor: 'blue' },
{ color: 'blue', cx: 60, cy: 60, subCircleColor: 'green' },
{ color: 'green', cx: 90, cy: 90 },
];
// Create a group which will hold the circles, since the result will
// be:
// <g class="circles">
// <circle color="{{ color }}" ... />
// <circle class="sub-circle" color="{{ subCircleColor }}" ... />
// </g>
var circlesGroups = svg.selectAll("g.circles")
.data(circles)
.enter()
.append("g").attr({"class": "circles"})
// Add the first circle to the group
circlesGroups
.append("circle").attr({
"fill": function(d) { return d.color },
"r": 20,
"cx": function(d) { return d.cx },
"cy": function(d) { return d.cy },
})
// If there is a subCircleColor, add the second circle to the group
circlesGroups.selectAll("circle.sub-circle")
.data(function(d) {
if (d.subCircleColor)
return [d];
return [];
})
.enter()
.append("circle").attr({
"class": "sub-circle",
"fill": function(d) { return d.subCircleColor; },
"r": 10,
"cx": function(d) { return d.cx },
"cy": function(d) { return d.cy },
})
答案 2 :(得分:1)
尝试使用此模式,可以删除或隐藏您的圈子。
// Step 1: hides all circles which are "null"
d3.selectAll(".yourItem")
.data(data)
.enter()
.append("circle")
.attr("visibility", function(d,i){
if(yourFunction(d) == null) return "hidden";
})
// Step 2: optional, deletes all circles which are "hidden"
d3.selectAll("circle[visibility=hidden]").remove();
答案 3 :(得分:1)
如果您想从不首先添加它,这是一种方法。我在.each()中使用了if语句,然后在d3.select(this)中将它附加到当前项目。
var data = [9, 0, 7, 0, 5, 0, 3, 0, 1];
var svg = d3.select('#svg').append('svg').attr({'viewBox': '-10 -10 99 20'});
svg.selectAll('g').data(data).enter().append('g').each(function (d,i) {
if(d){
d3.select(this).append('circle').attr({r:5,cx:(i*9)});
}else{
d3.select(this).remove();
}
});
答案 4 :(得分:-1)
只是过滤它。
values.filter(function(el){return el !== null;})