CStreet
CStreet

Reputation: 383

D3 Scatterplot legend overlapping

I have a scatterplot that works fine, but the legend I add to it is overlapping the chart. My current approach is to make the chart DIV be 70% of the width and have the legend take up the remaining 30%. For some reason, the legend isn't showing up on the screen, even though the HTML is there.

This is the link to my initial problem: http://jsfiddle.net/chp5a09e/373/

Here is the link to what I'm currently trying: http://jsfiddle.net/chp5a09e/372/

var legend = d3.select("#legend").append("svg")
    .attr("width", $("#legend").width())
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

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

  legend.append("rect")
    .attr("x", width - 12)
    .attr("width", 12)
    .attr("height", 12)
    .style("fill", function(d) {
      return color(d);
    })
    .on("click", function(d) {
      d3.selectAll(".symbol").style("opacity", 1)

      if (clicked !== d) {
        d3.selectAll(".symbol")
          .filter(function(e) {
            return e.items[columns.indexOf("Channel")] !== d;
          })
          .style("opacity", 0.1)
        clicked = d
      } else {
        clicked = ""
      }
    });

  legend.append("text")
    .attr("x", width - 16)
    .attr("y", 6)
    .attr("dy", ".35em")
    .style("text-anchor", "end")
    .text(function(d) {
      return d;
    });

Upvotes: 0

Views: 193

Answers (1)

Coderino Javarino
Coderino Javarino

Reputation: 2881

HTML is there

Only group (g) elements are there, and they are never visible themselves. In your original code

var legend = svg.selectAll(".legend")
    .data(color.domain())
    .enter().append("g")
    ...

  legend.append("rect")

the legend here is a selection of multiple g.legend elements, and thus a rect gets appended to each of them, as well as gets access to the datum bound to the parent g. However in you new code

var legend = d3.select("#legend").append("svg")
    ...
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  legend.selectAll(".legend")
    .data(color.domain())
    .enter().append("g")
    ...;

  legend.append("rect")

The legend here refers only to the single g element that contains your whole legend. Your legend.selectAll(".legend") isn't saved into variable, so while inside the chain you set class and transform attributes properly, you don't use it to get rect appended to it -- again, legend at that point refers to the outter single g container.


Potential solution:

var legendCnt = d3.select("#legend").append("svg")
    .attr("width", $("#legend").width())
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var legend = legendCnt.selectAll(".legend")
    .data(color.domain())
...

You'll notice you'll need to remove or lower x attribute for text and rect, since 0 is now at the beginning of the legend instead of chart

Upvotes: 1

Related Questions