我是 D3.js 的新手,我的垂直条形图有问题。出于某种原因,当我使用 rangeRoundBands 进行缩放时,轴和条形之间的距离太大了。 在API中,是这样解释的:
所以问题似乎是outerPadding。但是将 outerPadding 设置为零并没有帮助。但是,当我改用 rangeBands 时,问题就消失了,条形图的位置正确,就在轴的正下方。但是我会得到这些讨厌的抗锯齿效果,所以这不是一个真正的选择。这是我的代码:
var margin = {top: 40, right: 40, bottom: 20, left: 20},
width = 900 - margin.left - margin.right,
height = x - margin.top - margin.bottom;
var x = d3.scale.linear().range([0, width]);
var y = d3.scale.ordinal().rangeRoundBands([0, height], .15, 0);
var xAxis = d3.svg.axis()
.scale(x)
.orient("top");
var xAxis2 = d3.svg.axis()
.scale(x)
.orient("bottom");
var xAxis3 = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickSize(-height, 0, 0)
.tickFormat("");
var svg = d3.select("#plotContainer").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
x.domain(d3.extent(data, function(d) {
return d.size;
})).nice();
y.domain(data.map(function(d) {
return d.name;
}));
svg.append("g")
.attr("class", "x axis")
.call(xAxis);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis2);
svg.append("g")
.attr("class", "grid")
.attr("transform", "translate(0," + height + ")")
.call(xAxis3);
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", function(d) {
return d.size < 0 ? "bar negative" : "bar positive";
})
.attr("x", function(d) {
return x(Math.min(0, d.size));
})
.attr("y", function(d) {
return y(d.name);
})
.attr("width", function(d) {
return Math.abs(x(d.size) - x(0));
})
.attr("height", y.rangeBand())
.append("title")
.text(function(d) {
return "This value is " + d.name;
});
;
svg.selectAll(".bar.positive")
.style("fill", "steelblue")
.on("mouseover", function(d) {
d3.select(this).style("fill", "yellow");
})
.on("mouseout", function(d) {
d3.select(this).style("fill", "steelblue");
});
svg.selectAll(".bar.negative")
.style("fill", "brown")
.on("mouseover", function(d) {
d3.select(this).style("fill", "yellow");
})
.on("mouseout", function(d) {
d3.select(this).style("fill", "brown");
});
svg.selectAll(".axis")
.style("fill", "none")
.style("shape-rendering", "crispEdges")
.style("stroke", "#000")
.style("font", "10px sans-serif");
svg.selectAll(".grid")
.style("fill", "none")
.style("stroke", "lightgrey")
.style("opacity", "0.7");
svg.selectAll(".grid.path")
.style("stroke-width", "0");
编辑: 请看看这个 fiddle : http://jsfiddle.net/GUYZk/9/
我的问题在那里可以重现。您不能使用 rangeRoundBands 改变 outerPadding,而 rangeBands 表现正常。
最佳答案
TL;DR:这是数学的结果。要变通,请使用 rangeBands
布置条形,并使用 shape-rendering: crispEdges
在 CSS 中将它们与像素边界对齐。
完整解释:
因为 rangeRoundBands
函数必须在提供的像素范围内均匀分布条形图 AND 它还必须提供一个整数 rangeBand
,它使用 Math.floor
以切断每个连续柱的小数位。
这种额外的外部填充与更长的数据集复合的原因是因为所有这些小数像素都必须在某处结束。这个函数的作者选择在范围的开始和结束之间平均分配它们。
因为每个圆条的分数像素位于区间 (0, 1)
上,所以在每一端 glommed 的额外像素将跨越数据条计数的大约 1/4。如果有 10 个条,2-3 个额外的像素将永远不会被注意到,但如果有 100 个或更多,额外的 25+ 个像素会变得更加明显。
在 Chrome 中似乎适用于 svg:rect
的一种可能解决方案:使用 rangeBands
进行布局,然后应用 shape-rendering: crispEdges
作为您的栏路径/矩形的 CSS 样式。
这就让 SVG 渲染器有责任将每个条形微调到像素边界,但它们总体上间隔更均匀,间距偶尔会出现变化以解释整个图表的错误。
就我个人而言,我使用 shape-rendering: optimizeSpeed
并让渲染代理做出必要的权衡以快速渲染(可能是分数的)条形位置。
关于javascript - 条形图中的 rangeRoundBands outerPadding 太大了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23127172/