2014-02-05 143 views
0

我想添加一個圖例添加到D3散點圖矩陣(使用此示例作爲模板:http://bl.ocks.org/mbostock/4063663),而散點圖本身正在按預期方式顯示,但我一直無法成功添加一個傳奇。的情節,並在加入一個傳奇的代碼的嘗試之一是如下:將圖例添加到D3散點圖矩陣

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; }); 

所有根據我在網上找到的例子。這些方法似乎都沒有奏效 - 我必須在這裏錯過一些東西。任何見解或建議將不勝感激。

回答

0

的問題是正確的開頭:

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

selectAll('g')會已經在你的圖來選擇其中一個組,然後什麼都不會發生,因爲enter()表明,包括一切從那裏(值保存到legend變量)僅適用於尚不存在的組。

我很確定這個圖例代碼應該從運行在它自己的<g>元素內。這樣,它不會干擾你的圖形的其餘部分。

var legendGroup = svg.append('g') 
        .attr('class', 'legend') 
        .attr('transform', /* translate as appropriate */); 

var legendEntry = legendGroup.selectAll('g') 
        .data(dataset); 
      //create one legend entry for each series in the dataset array 
      //if that's not what you want, create an array that has one 
      //value for every entry you want in the legend 

legendEntry.enter().append("g") 
     .attr("class", "legend-entry") 
     .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; }); 
      //shift each entry down by approx 1 line (20px) 

legendEntry.append("rect") //add a square to each entry 
     /* and so on */ 
+0

如果您想讓圖例與顏色與物種相關聯,您可以給您的示例代碼提供Iris數據集嗎?我還不清楚在什麼地方你有什麼意見 – user3203010