toolkit/javascript/d3/examples/splom/splom.js
changeset 47 c0b4a8b5a012
equal deleted inserted replaced
46:efd9c589177a 47:c0b4a8b5a012
       
     1 d3.json("flowers.json", function(flower) {
       
     2 
       
     3   // Size parameters.
       
     4   var size = 150,
       
     5       padding = 19.5,
       
     6       n = flower.traits.length;
       
     7 
       
     8   // Position scales.
       
     9   var x = {}, y = {};
       
    10   flower.traits.forEach(function(trait) {
       
    11     var value = function(d) { return d[trait]; },
       
    12         domain = [d3.min(flower.values, value), d3.max(flower.values, value)],
       
    13         range = [padding / 2, size - padding / 2];
       
    14     x[trait] = d3.scale.linear().domain(domain).range(range);
       
    15     y[trait] = d3.scale.linear().domain(domain).range(range.reverse());
       
    16   });
       
    17 
       
    18   // Axes.
       
    19   var axis = d3.svg.axis()
       
    20       .ticks(5)
       
    21       .tickSize(size * n);
       
    22 
       
    23   // Brush.
       
    24   var brush = d3.svg.brush()
       
    25       .on("brushstart", brushstart)
       
    26       .on("brush", brush)
       
    27       .on("brushend", brushend);
       
    28 
       
    29   // Root panel.
       
    30   var svg = d3.select("#chart").append("svg:svg")
       
    31       .attr("width", size * n + padding)
       
    32       .attr("height", size * n + padding);
       
    33 
       
    34   // X-axis.
       
    35   svg.selectAll("g.x.axis")
       
    36       .data(flower.traits)
       
    37     .enter().append("svg:g")
       
    38       .attr("class", "x axis")
       
    39       .attr("transform", function(d, i) { return "translate(" + i * size + ",0)"; })
       
    40       .each(function(d) { d3.select(this).call(axis.scale(x[d]).orient("bottom")); });
       
    41 
       
    42   // Y-axis.
       
    43   svg.selectAll("g.y.axis")
       
    44       .data(flower.traits)
       
    45     .enter().append("svg:g")
       
    46       .attr("class", "y axis")
       
    47       .attr("transform", function(d, i) { return "translate(0," + i * size + ")"; })
       
    48       .each(function(d) { d3.select(this).call(axis.scale(y[d]).orient("right")); });
       
    49 
       
    50   // Cell and plot.
       
    51   var cell = svg.selectAll("g.cell")
       
    52       .data(cross(flower.traits, flower.traits))
       
    53     .enter().append("svg:g")
       
    54       .attr("class", "cell")
       
    55       .attr("transform", function(d) { return "translate(" + d.i * size + "," + d.j * size + ")"; })
       
    56       .each(plot);
       
    57 
       
    58   // Titles for the diagonal.
       
    59   cell.filter(function(d) { return d.i == d.j; }).append("svg:text")
       
    60       .attr("x", padding)
       
    61       .attr("y", padding)
       
    62       .attr("dy", ".71em")
       
    63       .text(function(d) { return d.x; });
       
    64 
       
    65   function plot(p) {
       
    66     var cell = d3.select(this);
       
    67 
       
    68     // Plot frame.
       
    69     cell.append("svg:rect")
       
    70         .attr("class", "frame")
       
    71         .attr("x", padding / 2)
       
    72         .attr("y", padding / 2)
       
    73         .attr("width", size - padding)
       
    74         .attr("height", size - padding);
       
    75 
       
    76     // Plot dots.
       
    77     cell.selectAll("circle")
       
    78         .data(flower.values)
       
    79       .enter().append("svg:circle")
       
    80         .attr("class", function(d) { return d.species; })
       
    81         .attr("cx", function(d) { return x[p.x](d[p.x]); })
       
    82         .attr("cy", function(d) { return y[p.y](d[p.y]); })
       
    83         .attr("r", 3);
       
    84 
       
    85     // Plot brush.
       
    86     cell.call(brush.x(x[p.x]).y(y[p.y]));
       
    87   }
       
    88 
       
    89   // Clear the previously-active brush, if any.
       
    90   function brushstart(p) {
       
    91     if (brush.data !== p) {
       
    92       cell.call(brush.clear());
       
    93       brush.x(x[p.x]).y(y[p.y]).data = p;
       
    94     }
       
    95   }
       
    96 
       
    97   // Highlight the selected circles.
       
    98   function brush(p) {
       
    99     var e = brush.extent();
       
   100     svg.selectAll("circle").attr("class", function(d) {
       
   101       return e[0][0] <= d[p.x] && d[p.x] < e[1][0]
       
   102           && e[0][1] <= d[p.y] && d[p.y] < e[1][1]
       
   103           ? d.species : null;
       
   104     });
       
   105   }
       
   106 
       
   107   // If the brush is empty, select all circles.
       
   108   function brushend() {
       
   109     if (brush.empty()) svg.selectAll("circle").attr("class", function(d) {
       
   110       return d.species;
       
   111     });
       
   112   }
       
   113 
       
   114   function cross(a, b) {
       
   115     var c = [], n = a.length, m = b.length, i, j;
       
   116     for (i = -1; ++i < n;) for (j = -1; ++j < m;) c.push({x: a[i], i: i, y: b[j], j: j});
       
   117     return c;
       
   118   }
       
   119 });