44 Stimmen

Hinzufügen einer Legende für das Diagramm in D3

Ich habe Schwierigkeiten, eine Legende zu meinem d3js-Diagramm hinzuzufügen. Hier ist mein aktueller Ansatz:

var legend = svg.append("g")
  .attr("class", "legend")
  .attr("x", w - 65)
  .attr("y", 25)
  .attr("height", 100)
  .attr("width", 100);

legend.append("rect")
  .attr("x", w - 65)
  .attr("y", 25)
  .attr("width", 10)
  .attr("height", 10)
  .style("fill", function(d) { return color_hash[dataset.indexOf(d)][1] });

legend.append("text")
  .attr("x", w - 65)
  .attr("y", 25)
  .text(function(d) { return color_hash[dataset.indexOf(d)][0] + ": " + d; });

Dann versuche ich, die .legend Klasse zu stylen:

.legend {
            padding: 5px;
            font: 10px sans-serif;
            background: yellow;
            box-shadow: 2px 2px 1px #888;
        }

Aber ich habe nicht viel Glück.

Kennt sich jemand damit aus, Legenden zu Diagrammen hinzuzufügen und kann den besten Weg dazu angeben? Ich finde nicht viele Ressourcen dazu online.

Hier ist mein gesamter Graph: http://jsbin.com/ewiwag/2/edit

41voto

jaime Punkte 41821

Sie müssen Daten an die Knoten (Rechtecke und Textelemente) binden, die die Legende bilden.

Derzeit erhalten Sie einen Fehler, wenn Sie versuchen, Rechtecke zu stylen:

Uncaught TypeError: Kann Eigenschaft '1' von undefiniert nicht lesen 

Der Grund: es gibt keine gebundenen Daten

legend.append("rect")
      /*...*/
      .style("fill", function(d) { 
         // d <---- ist undefiniert
         return color_hash[dataset.indexOf(d)][1] 
      });

Beachten Sie, dass D3 auf Daten transformation fokussiert und auf Selektionen operiert. Wählen Sie also zuerst eine Gruppe von Knoten aus und binden Sie dann Daten

legend.selectAll('rect')
      .data(dataset)
      .enter()

Sobald Sie die Selektion mit enter betreten, können Sie Knoten hinzufügen und Eigenschaften dynamisch anwenden. Beachten Sie, dass Sie beim Festlegen der y-Eigenschaft den i-Zähler übergeben und mit einer Ganzzahl multiplizieren, um zu verhindern, dass Rechtecke übereinander erstellt werden.

  /*.....*/
      .append("rect")
      .attr("x", w - 65)
      .attr("y", function(d, i){ return i *  20;})
      .attr("width", 10)
      .attr("height", 10)
      .style("fill", function(d) { 
         var color = color_hash[dataset.indexOf(d)][1];
         return color;
      });

Hier ist das behobene Beispiel: http://jsbin.com/ubafur/3

13voto

meetamit Punkte 24263

Ok, hier ist eine Möglichkeit, es zu tun: http://jsbin.com/isuris/1/edit

Tut mir leid, ich musste zu viele Änderungen vornehmen, um alles erklären zu können. Schau mal, ob du es herausfinden kannst. Wenn du Fragen hast, stelle sie in den Kommentaren, und ich werde die Antwort ändern.

      .axis path,
      .axis line {
        fill: none;
        stroke: black;
        shape-rendering: crispEdges;
      }

      .axis text {
        font-family: sans-serif;
        font-size: 11px;
      }

      .y1 {
        fill: white;
        stroke: orange;
        stroke-width: 1.5px;
      }

      .y2 {
        fill: white;
        stroke: red;
        stroke-width: 1.5px;
      }

      .y3 {
        fill: white;
        stroke: steelblue;
        stroke-width: 1.5px;
      }

      .line {
        fill: none;
        stroke-width: 1.5px;
      }

      div.tooltip {
              position: absolute;
              text-align: center;
              width: 50px;
              height: 10px;
              padding: 5px;
              font: 10px sans-serif;
              background: whiteSmoke;
              border: solid 1px #aaa;
              pointer-events: none;
              box-shadow: 2px 2px 1px #888;
            }

            .legend {
              padding: 5px;
              font: 10px sans-serif;
              background: yellow;
              box-shadow: 2px 2px 1px #888;
            }

            .title {
              font: 13px sans-serif;
            }

    //Breite und Höhe
    var w = 500;
    var h = 300;
    var padding = 50;

    var now = d3.time.hour.utc(new Date);
    var dataset = [ [ ],[ ] ];
    dataset[0].push({x: d3.time.hour.utc.offset(now, -5), y: 0});
    dataset[0].push({x: d3.time.hour.utc.offset(now, -4), y: 0});
    dataset[0].push({x: d3.time.hour.utc.offset(now, -3), y: 2});
    dataset[0].push({x: d3.time.hour.utc.offset(now, -2), y: 0});
    dataset[0].push({x: d3.time.hour.utc.offset(now, -1), y: 0});
    dataset[0].push({x: now, y: 0});

    dataset[1].push({x: d3.time.hour.utc.offset(now, -5), y: 3});
    dataset[1].push({x: d3.time.hour.utc.offset(now, -4), y: 1});
    dataset[1].push({x: d3.time.hour.utc.offset(now, -3), y: 3});
    dataset[1].push({x: d3.time.hour.utc.offset(now, -2), y: 1});
    dataset[1].push({x: d3.time.hour.utc.offset(now, -1), y: 5});
    dataset[1].push({x: now, y: 1});

    var color_hash = {  0 : ["apple", "green"],
              1 : ["mango", "orange"],
              2 : ["cherry", "red"]
            }                      

    // Achsenbereiche & Skalen definieren        
    var yExtents = d3.extent(d3.merge(dataset), function (d) { return d.y; });
    var xExtents = d3.extent(d3.merge(dataset), function (d) { return d.x; });

  var xScale = d3.time.scale()
         .domain([xExtents[0], xExtents[1]])
         .range([padding, w - padding * 2]);

  var yScale = d3.scale.linear()
         .domain([0, yExtents[1]])
         .range([h - padding, padding]);

  // SVG-Element erstellen
  var svg = d3.select("body")
      .append("svg")
      .attr("width", w)
      .attr("height", h);

  // Linien definieren
  var line = d3.svg.line()
         .x(function(d) { return x(d.x); })
         .y(function(d) { return y(d.y1, d.y2, d.y3); });

  var pathContainers = svg.selectAll('g.line')
  .data(dataset);

  pathContainers.enter().append('g')
  .attr('class', 'line')
  .attr("style", function(d) {
    return "stroke: " + color_hash[dataset.indexOf(d)][1]; 
  });

  pathContainers.selectAll('path')
  .data(function (d) { return [d]; }) // setzt die Daten vom pathContainer fort
  .enter().append('path')
    .attr('d', d3.svg.line()
      .x(function (d) { return xScale(d.x); })
      .y(function (d) { return yScale(d.y); })
    );

  // Kreise hinzufügen
  pathContainers.selectAll('circle')
  .data(function (d) { return d; })
  .enter().append('circle')
  .attr('cx', function (d) { return xScale(d.x); })
  .attr('cy', function (d) { return yScale(d.y); })
  .attr('r', 3); 

    // X-Achse definieren
  var xAxis = d3.svg.axis()
          .scale(xScale)
          .orient("bottom")
          .ticks(5);

  // Y-Achse definieren
  var yAxis = d3.svg.axis()
          .scale(yScale)
          .orient("left")
          .ticks(5);

  // X-Achse hinzufügen
  svg.append("g")
  .attr("class", "axis")
  .attr("transform", "translate(0," + (h - padding) + ")")
  .call(xAxis);

  // Y-Achse hinzufügen
  svg.append("g")
  .attr("class", "axis")
  .attr("transform", "translate(" + padding + ",0)")
  .call(yAxis);

  // Titel hinzufügen    
  svg.append("svg:text")
       .attr("class", "title")
     .attr("x", 20)
     .attr("y", 20)
     .text("Obstverkauf pro Stunde");

  // Legende hinzufügen   
  var legend = svg.append("g")
    .attr("class", "legend")
    .attr("x", w - 65)
    .attr("y", 25)
    .attr("height", 100)
    .attr("width", 100);

  legend.selectAll('g').data(dataset)
      .enter()
      .append('g')
      .each(function(d, i) {
        var g = d3.select(this);
        g.append("rect")
          .attr("x", w - 65)
          .attr("y", i*25)
          .attr("width", 10)
          .attr("height", 10)
          .style("fill", color_hash[String(i)][1]);

        g.append("text")
          .attr("x", w - 50)
          .attr("y", i * 25 + 8)
          .attr("height",30)
          .attr("width",100)
          .style("fill", color_hash[String(i)][1])
          .text(color_hash[String(i)][0]);

      });

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X