将图例添加到d3 scatterplot矩阵

时间:2014-02-05 23:38:58

标签: javascript html svg d3.js

我正在尝试将图例添加到d3散点图矩阵(使用此示例作为模板:http://bl.ocks.org/mbostock/4063663),并且当散点图本身按预期显示时,我无法成功添加图例。情节的代码和添加图例的尝试之一如下:

var width = 960,
size = 150,
padding = 19.5;

var x = d3.scale.linear()
    .range([padding / 2, size - padding / 2]);

var y = d3.scale.linear()
    .range([size - padding / 2, padding / 2]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")
    .ticks(5);

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left")
    .ticks(5);

var color = d3.scale.category10();





d3.csv(datafilename, function(error, dataset) {
  var domainByTrait = {},
      traits = d3.keys(dataset[0]).filter(function(d) { return d !== "class"; }),
      n = traits.length;

  traits.forEach(function(trait) {
    domainByTrait[trait] = d3.extent(dataset, function(d) { return d[trait]; });
  });

  xAxis.tickSize(size * n);
  yAxis.tickSize(-size * n);

  var brush = d3.svg.brush()
      .x(x)
      .y(y)
      .on("brushstart", brushstart)
      .on("brush", brushmove)
      .on("brushend", brushend);

  var svg = d3.select("#visualizationDiv").append("svg")
      .attr("width", size * n + padding)
      .attr("height", size * n + padding)
    .append("g")
      .attr("transform", "translate(" + padding + "," + padding / 2 + ")");

  svg.selectAll(".x.axis")
      .data(traits)
    .enter().append("g")
      .attr("class", "x axis")
      .attr("transform", function(d, i) { return "translate(" + (n - i - 1) * size + ",0)"; })
      .each(function(d) { x.domain(domainByTrait[d]); d3.select(this).call(xAxis); });

  svg.selectAll(".y.axis")
      .data(traits)
    .enter().append("g")
      .attr("class", "y axis")
      .attr("transform", function(d, i) { return "translate(0," + i * size + ")"; })
      .each(function(d) { y.domain(domainByTrait[d]); d3.select(this).call(yAxis); });

  var cell = svg.selectAll(".cell")
      .data(cross(traits, traits))
    .enter().append("g")
      .attr("class", "cell")
      .attr("transform", function(d) { return "translate(" + (n - d.i - 1) * size + "," + d.j * size + ")"; })
      .each(plot);

  // Titles for the diagonal.
  cell.filter(function(d) { return d.i === d.j; }).append("text")
      .attr("x", padding)
      .attr("y", padding)
      .attr("dy", ".71em")
      .text(function(d) { return d.x; });

  cell.call(brush);

  function plot(p) {
    var cell = d3.select(this);

    x.domain(domainByTrait[p.x]);
    y.domain(domainByTrait[p.y]);

    cell.append("rect")
        .attr("class", "frame")
        .attr("x", padding / 2)
        .attr("y", padding / 2)
        .attr("width", size - padding)
        .attr("height", size - padding);

    cell.selectAll("circle")
        .data(dataset)
      .enter().append("circle")
        .attr("cx", function(d) { return x(d[p.x]); })
        .attr("cy", function(d) { return y(d[p.y]); })
        .attr("r", 3)
        .style("fill", function(d) { return color(d.class); });
  }

  var brushCell;

  // Clear the previously-active brush, if any.
  function brushstart(p) {
    if (brushCell !== this) {
      d3.select(brushCell).call(brush.clear());
      x.domain(domainByTrait[p.x]);
      y.domain(domainByTrait[p.y]);
      brushCell = this;
    }
  }

  // Highlight the selected circles.
  function brushmove(p) {
    var e = brush.extent();
    svg.selectAll("circle").classed("hidden", function(d) {
      return e[0][0] > d[p.x] || d[p.x] > e[1][0]
          || e[0][1] > d[p.y] || d[p.y] > e[1][1];
    });
  }

  // If the brush is empty, select all circles.
  function brushend() {
    if (brush.empty()) svg.selectAll(".hidden").classed("hidden", false);
  }

  function cross(a, b) {
    var c = [], n = a.length, m = b.length, i, j;
    for (i = -1; ++i < n;) for (j = -1; ++j < m;) c.push({x: a[i], i: i, y: b[j], j: j});
    return c;
  }

  d3.select(self.frameElement).style("height", size * n + padding + 20 + "px");








// add legend   
var legend = svg.append("g")
   .attr("class", "legend")
       .attr("height", 100)
       .attr("width", 100)
       .attr('transform', 'translate(-20,50)');    


legend.selectAll('rect')
  .data(dataset)
  .enter()
  .append("rect")
  .attr("x", width - 65)
  .attr("y", function(d, i){ return i *  20;})
  .attr("width", 10)
  .attr("height", 10)
  .style("fill", function(d) { return color(d.class); });

legend.selectAll('text')
  .data(dataset)
  .enter()
  .append("text")
  .attr("x", width - 52)
  .attr("y", function(d, i){ return i *  20 + 9;})
  .text(function(d) { return d.class; });

});

我添加传奇的其他尝试失败是

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

 legend.append("rect")
      .attr("x", width - 28)
      .attr("width", 18)
      .attr("height", 18)
      .style("fill", function(d) { return color(d.class); });

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

 var legend = svg.selectAll('g').data(dataset)
  .enter()
  .append('g')
  .attr("class", "legend");

legend.append("rect")
  .attr("x", width - 45)
  .attr("y", 25)
  .attr("height", 50)
  .attr("width", 50)
  .each(function(d, i) {
    var g = d3.select(this);
    g.append("rect")
      .attr("x", width - 65)
      .attr("y", i*25)
      .attr("width", 10)
      .attr("height", 10)
      .style("fill", function(d) { return color(d.class); });

    g.append("text")
      .attr("x", width - 50)
      .attr("y", i * 25 + 8)
      .attr("height",30)
      .attr("width",100)
      .style("fill", function(d) { return color(d.class); })
      .text(function(d) { return d.class; });

所有这些都基于我在网上找到的例子。这些方法似乎都没有起作用 - 我必须在这里遗漏一些东西。任何见解或建议都将不胜感激。

1 个答案:

答案 0 :(得分:0)

问题恰好在一开始:

var legend = svg.selectAll('g').data(dataset)
  .enter()
  .append('g')
  .attr("class", "legend");

selectAll('g')将选择图表中已有的其中一个组,然后不会发生任何事情,因为enter()表示从那里开始的所有内容(包括保存到{{的值) 1}}变量)仅适用于尚不存在的组。

我很确定这个图例代码应该从在自己的legend元素中运行。这样,它就不会干扰图表的其余部分。

<g>
相关问题