替换xaxis

时间:2017-06-11 19:14:17

标签: d3.js

我使用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");

2 个答案:

答案 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)解决方案,但这个有效。