在水平条形图上的条形后面添加文本

时间:2019-04-17 11:11:24

标签: javascript d3.js svg

我正在制作水平条形图,我想在条形图后移动y标签。

d3.csv("mydata.csv", function(data) {

    // Add X axis
    var x = d3.scaleLinear()
        .domain([0, 100])
        .range([ 0, width])

    svg.append("g")
        .attr("transform", "translate(0,0)")
        .call(d3.axisTop(x).ticks(10).tickFormat(function(d){return d+ "%"}))
        .selectAll("text")
        .attr("transform", "translate(10,-12)rotate(-45)")
        .style("text-anchor", "end");

    // Y axis
    var y = d3.scaleBand()
        .range([ 0, height ])
        .domain(data.map(function(d) { return d.type; }))
        .padding(.5);

    svg.append("g")
        .call(d3.axisRight(y))
        .selectAll('text')
        .attr("x", function(d) { return d.number; } )

    //Bars
    svg.selectAll("myRect")
        .data(data)
        .enter()
        .append("rect")
        .attr("x", x(0.5) )
        .attr("y", function(d) { return y(d.type); })
        .attr("width", function(d) { return x(d.number); })
        .attr("height", y.bandwidth() )
        .attr("fill", "#69b3a2")

})

CSV文件有两列

  • 类型
  • 号码

在这部分代码上

  svg.append("g")
        .call(d3.axisRight(y))
        .selectAll('text')
        .attr("x", function(d) { return d.number; } )

如果我将.attr("x", function(d) { return d.number; } )行替换为 .attr("x", 100 )然后将标签向右移动。但是,当我尝试通过条形图的宽度使它保持动态时,文本保持在y轴的开始。

1 个答案:

答案 0 :(得分:2)

在您的代码中,您试图移动轴的刻度,而不是使用标签作为<text>元素来创建新的选择!这是一种非常不常见的方法,但是肯定是可行的。

主要问题只是数据:在这一行...

.attr("x", function(d) { return d.number; })

...原点(d)与矩形所具有的原点不同,该原点来自您的数据。此处的数据只是轴刻度中的字符串。

因此,我们必须获取实际数据,因此我们可以获取number值。像这样:

.attr("x", function(d) {
    const datum = data.find(function(e){return e.type === d})
    return x(datum.number);
})

这是您所做的更改(和一些伪造数据)的代码:

var width = 500,
  height = 300,
  padding = 20;

var data = [{
    type: "foo",
    number: 42
  },
  {
    type: "bar",
    number: 12
  },
  {
    type: "baz",
    number: 79
  },
  {
    type: "foobar",
    number: 17
  },
  {
    type: "foobaz",
    number: 36
  }
];

var svg = d3.select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height);

var x = d3.scaleLinear()
  .domain([0, 100])
  .range([padding, width - padding])

svg.append("g")
  .attr("transform", "translate(0,20)")
  .call(d3.axisTop(x).ticks(10).tickFormat(function(d) {
    return d + "%"
  }))
  .selectAll("text")
  .attr("transform", "translate(10,-12)rotate(-45)")
  .style("text-anchor", "end");

// Y axis
var y = d3.scaleBand()
  .range([padding, height - padding])
  .domain(data.map(function(d) {
    return d.type;
  }))
  .padding(0.5);

svg.append("g")
  .attr("transform", "translate(20,0)")
  .call(d3.axisRight(y))
  .selectAll('text')
  .attr("x", function(d) {
    const datum = data.find(function(e) {
      return e.type === d
    })
    return x(datum.number) + 6;
  })

//Bars
svg.selectAll("myRect")
  .data(data)
  .enter()
  .append("rect")
  .attr("x", x(0.5))
  .attr("y", function(d) {
    return y(d.type);
  })
  .attr("width", function(d) {
    return x(d.number);
  })
  .attr("height", y.bandwidth())
  .attr("fill", "#69b3a2")
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>