d3.js在图例中水平绘制矩形框

时间:2017-10-15 11:18:16

标签: d3.js svg

我想在图表顶部水平显示图例,我做了类似的事情:

var legend = svg.selectAll(".legend")
    .data(color.domain())
    .enter().append("g")
    .attr("class", "legend")
    .attr("transform", function(d, i) {
        return "translate(0," + i * 30 +
            ")";
    });

legend.append("rect")
    .attr("x", function(d, i) {
        return (i * 150) + 400;
    })
    .attr("y", function(d, i) {
        return 350;
    })
    .attr("width", 18)
    .attr("height", 18)
    .style("fill", color);

我的数据看起来像Rect1 - North, Rect-2 - North East,我的问题只是散点图图表顶部的图例框对齐。

enter image description here

1 个答案:

答案 0 :(得分:2)

水平绘制图例的最大问题是文字:由于North West大于East,因此您无法简单地对要翻译的值进行硬编码。

在此解决方案中,我将使用getComputedTextLength(顾名思义)获取每个文本的长度并使用D3 locals存储这些值。

因此,当我绘制文本时,我将它们的长度存储在父<g>元素中:

var local = d3.local();

legend.append("text")
  .text(String)
  .attr("y", function() {
    local.set(this.parentNode, this.getComputedTextLength())
    return 20;
  });

之后,我使用该值绘制矩形......

legend.append("rect")
  .attr("x", function() {
    return local.get(this.parentNode) + 4
  });

...并翻译小组:

legend.each(function(d, i) {
  if (i) {
    d3.select(this).attr("transform", "translate(" + 
        (counter += local.get(this.previousSibling) + 36) + ",0)")
  }
})

以下是使用此数据的演示:

["North", "North East", "North West", "West", "East"];

var svg = d3.select("svg");
var data = ["North", "North East", "North West", "West", "East"];
var colors = d3.scaleOrdinal(d3.schemeCategory10);
var local = d3.local();
var legend = svg.selectAll(null)
  .data(data)
  .enter()
  .append("g");

legend.append("text")
  .text(String)
  .attr("y", function() {
    local.set(this.parentNode, this.getComputedTextLength())
    return 20;
  });

legend.append("rect")
  .style("fill", function(d, i) {
    return colors(i)
  })
  .attr("x", function() {
    return local.get(this.parentNode) + 4
  })
  .attr("y", 6)
  .attr("width", 18)
  .attr("height", 18);

var counter = 0;

legend.each(function(d, i) {
  if (i) {
    d3.select(this).attr("transform", "translate(" + (counter += local.get(this.previousSibling) + 36) + ",0)")
  }
})
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="100"></svg>