我使用d3的创建者使用this演示创建了一个分组的条形图(请参阅here了解工作的js小提琴)。沿xAxis,图表显示编号标签(0 - 19)。这些数字似乎用作默认值,因为数据样本(n)是长度为20的数组,并且没有其他显式代码将标签设置为等于数字。
问题:如何将这些标签设置为其他标签?
码
// create a range that is 20
var x0 = d3.scale.ordinal()
.domain(d3.range(n)) //n = 20 [0,1,2,...19]
.rangeBands([0, width], .2);
var x1 = d3.scale.ordinal()
.domain(d3.range(m)) // m = 4 , not relevant for this question
.rangeBands([0, x0.rangeBand()]);
var z = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x0) // xAxis is scaling the range of 20 along the bottom, there is no code setting the text of the label
.orient("bottom");
答案 0 :(得分:2)
与other answer建议的不同,您不需要两个比例。你可以用一个比例来完成所有这些:
i
问题是:在原始代码中,由于域只是一个整数数组,因此Bostock依赖于索引(.attr("x", function(d,i) { return x0(alphabet[i]); })
)来设置条的x位置。
最好的选择是创建一个数据数组,其中包含每个数据点的值(y位置)和字母(x位置)。但是,一个简单的替代方法(对原始代码进行最小的更改)是通过索引获取字母,如下所示:
var n = 20; // number of samples
var m = 4;
var data = d3.range(m).map(function() {
return d3.range(n).map(Math.random);
});
var margin = {
top: 20,
right: 30,
bottom: 30,
left: 40
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var y = d3.scale.linear()
.domain([0, 1])
.range([height, 0]);
var alphabet = "ABCDEFGHIJKLMNOPQRST".split("");
var x0 = d3.scale.ordinal()
.domain(alphabet)
.rangeBands([0, width], .2);
var x1 = d3.scale.ordinal()
.domain(d3.range(m))
.rangeBands([0, x0.rangeBand()]);
var z = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("svg:g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g").selectAll("g")
.data(data)
.enter().append("g")
.style("fill", function(d, i) {
return z(i);
})
.attr("transform", function(d, i) {
return "translate(" + x1(i) + ",0)";
})
.selectAll("rect")
.data(function(d) {
return d;
})
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("height", y)
.attr("x", function(d, i) {
return x0(alphabet[i]);
})
.attr("y", function(d) {
return height - y(d);
});
以下是更新的演示:
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
@current_level
答案 1 :(得分:-1)
一种方法是创建两个刻度,一个用于定位,一个用于标记
var x0 = d3.scale.ordinal()
.domain(d3.range(n)) //n = 20 [0,1,2,...19]
.rangeBands([0, width], .2);
var alphabet = d3.scale.ordinal()
.domain(d3.range(n)) //n = 20 ["a","b","c",..."t"]
.rangeBands([0, width], .2);
然后,使用其中一个创建xAxis,在这种情况下,它将放置默认标签&#34; a&#34;,&#34; b&#34;,&#34; c&#34;
this.xAxis = d3.svg.axis()
.scale(alphabet)
.orient("bottom");
附加rect
时,请使用其他比例进行定位
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("height", y)
.attr("x", function(d, i) { return x0(i); }) //will set position according to x0 scale
.attr("y", function(d) { return height - y(d); });
必须注意两个比例在数组中的长度和位置方面正确对齐,即如果n
是一个包含20个数字的数组,则另一个数组必须具有20个数组字母(如本例所示)。
我认为有一个更好的(更少hacky)解决方案,但这个有效。