无法使用D3更改组元素中图例文本的x位置

时间:2017-06-27 08:21:04

标签: d3.js visualization legend

我正在尝试在D3.js中创建一个水平图形图例。我使用组元素(g)作为所有图例的容器,并且各个图例(文本)也都包含在“g”元素中。结果是各个传说堆叠在一起而不是间隔开 我试过改变图例上的x属性并转换/翻译。虽然DOM显示应用了x值,但图例不会移动。因此,如果DOM显示图例/ g元素位于x = 200,则它仍然位于0。 我花了两天时间试图解决这个问题,并且可能会查看50多个示例,包括我在StackExchange上可以找到的任何内容。 下面的代码是我最近的尝试。它没有通过任何错误,并且x值反映在DOM中,但元素不会移动。

我已经包含了覆盖相关位的代码(但不是所有代码)。

此处添加了图例容器:

/*<note>Add container to hold legends. */
        var LegendCanvas = d3.select("svg")
            .append("g")
                .attr("class", "legend canvas")
                .attr("x", 0)
                .attr("y", 0)
                .attr("width", Width)
                .style("fill", "#ffcccc")
                .attr("transform", "translate(0,15)");

然后通过json对象数组循环:

        var PrevElemLength = 0;

        /*<note>Loop through each data series, call the Valueline variable and plot the line. */
        Data.forEach(function(Key, i) {
            /*<note>Add the metric line(s). */
            Svg.append("path")
                .attr("class", "line")
                .attr("data-legend",function() { return Key.OriginId })
                /*<note>Iterates through the data series objects and applies a different color to each line. */
                .style("stroke", function () {
                    return Key.color = Color(Key.UniqueName); })
                .attr("d", Valueline(Key.DataValues));

            /*<note>Add a g element to the legend container. */
            var Legend = LegendCanvas.append("g")
                .attr("class", "legend container")
                .attr("transform", function (d, i) {
                    if (i === 0) {
                        return "translate(0,0)"
                    } else { 
                        PrevElemLength += this.previousElementSibling.getBBox().width;
                        return "translate(" + (PrevElemLength) + ",0)"
                    }
                });

            /*<note>Adds a rectangle to pre-fix each legend. */
            Legend.append("rect")
                .attr("width", 5)
                .attr("height", 5)
                .style("fill", function () {
                    return Key.color = Color(Key.UniqueName); });

            /*<note>Adds the legend text. */
            Legend.append("text")
                .attr("x", function() {
                    return this.parentNode.getBBox().width + 5;
                })
                /*.attr("y", NetHeight + (Margin.bottom/2)+ 10) */
                .attr("class", "legend text")
                .style("fill", function () {
                    return Key.color = Color(Key.UniqueName); })
                .text(Key.UniqueName);

以下是输出结果的屏幕截图: enter image description here 任何有关如何创建水平图例(没有重叠传说)的帮助将非常感激。克里斯

2 个答案:

答案 0 :(得分:0)

问题是您在设置d属性时使用局部变量itransform作为函数参数。本地范围中的参数i会覆盖实际变量。局部变量i的值总是为零,因为没有数据绑定到该元素。

var Legend = LegendCanvas.append("g")
   .attr("class", "legend container")
   .attr("transform", function (d, i) { //Remove i
       if (i === 0) {
          return "translate(0,0)"
       } else { 
          PrevElemLength += this.previousElementSibling.getBBox().width;
          return "translate(" + (PrevElemLength) + ",0)"
       }
  });

我还对代码进行了一些改进。

&#13;
&#13;
var LegendCanvas = d3.select("svg")
  .append("g")
  .attr("class", "legend canvas")
  .attr("x", 0)
  .attr("y", 0)
  .attr("width", 500)
  .style("fill", "#ffcccc")
  .attr("transform", "translate(0,15)");
var PrevElemLength = 0;
var Data = [{
  OriginId: 1,
  UniqueName: "Some Long Text 1"
}, {
  OriginId: 2,
  UniqueName: "Some Long Text 2"
}];
/*<note>Loop through each data series, call the Valueline variable and plot the line. */
var Color = d3.scale.category10();
Data.forEach(function(Key, i) {

  /*<note>Add a g element to the legend container. */
  var Legend = LegendCanvas.append("g")
    .attr("class", "legend container")
    .attr("transform", function() {
      if (i === 0) {
        return "translate(0,0)"
      } else {
        var marginLeft = 5;
        PrevElemLength += this.previousElementSibling.getBBox().width;
        return "translate(" + (PrevElemLength + marginLeft) + ",0)"
      }
    });

  /*<note>Adds a rectangle to pre-fix each legend. */
  Legend.append("rect")
    .attr("width", 5)
    .attr("height", 5)
    .style("fill", function() {
      return Key.color = Color(Key.UniqueName);
    });

  /*<note>Adds the legend text. */
  Legend.append("text")
    .attr("x", function() {
      return this.parentNode.getBBox().width + 5;
    })
    .attr("dy", "0.4em")
    .attr("class", "legend text")
    .style("fill", function() {
      return Key.color = Color(Key.UniqueName);
    })
    .text(Key.UniqueName);
});
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg height=500 width=500></svg>
&#13;
&#13;
&#13;

d3实现方式(使用数据绑定)如下

&#13;
&#13;
var LegendCanvas = d3.select("svg")
  .append("g")
  .attr("class", "legend canvas")
  .attr("x", 0)
  .attr("y", 0)
  .attr("width", 500)
  .style("fill", "#ffcccc")
  .attr("transform", "translate(0,15)");

var Data = [{
  OriginId: 1,
  UniqueName: "Some Long Text 1"
}, {
  OriginId: 2,
  UniqueName: "Some Long Text 2"
}];

var Color = d3.scale.category10();

var Legend = LegendCanvas.selectAll(".legend")
  .data(Data)
  .enter()
  .append("g")
  .attr("class", "legend container");  

Legend.append("rect")
  .attr("width", 5)
  .attr("height", 5)
  .style("fill", function(Key) {
    return Key.color = Color(Key.UniqueName);
  });

Legend.append("text")
  .attr("x", function() {
    return this.parentNode.getBBox().width + 5;
  })
  .attr("dy", "0.4em")
  .attr("class", "legend text")
  .style("fill", function(Key) {
    return Key.color = Color(Key.UniqueName);
  })
  .text(function(Key){ return Key.UniqueName });

var PrevElemLength = 0;
Legend.attr("transform", function(d, i) {
    if (i === 0) {
      return "translate(0,0)"
    } else {
      var marginLeft = 5;
      PrevElemLength += this.previousElementSibling.getBBox().width;
      return "translate(" + (PrevElemLength + marginLeft) + ",0)"
    }
  });  
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width=500 height=500></svg>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

试试这个:

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

    legend.append("image")
        .attr("x", 890)
        .attr("y", 70)
        .attr("width", 20)
        .attr("height", 18)
        .attr("xlink:href",function (d) {
            return "../assets/images/dev/"+d+".png";
        })

    legend.append("text")
        .attr("x", 910)
        .attr("y", 78)
        .attr("dy", ".35em")
        .style("text-anchor", "start")
        .text(function(d) {
                return d;
        });