toolkit/javascript/d3/examples/sort/sort.js
changeset 47 c0b4a8b5a012
equal deleted inserted replaced
46:efd9c589177a 47:c0b4a8b5a012
       
     1 // Based on http://vis.stanford.edu/protovis/ex/sort.html
       
     2 // Based on work by Robert Sedgewick
       
     3 
       
     4 var w = 960,
       
     5     h = 50,
       
     6     n = 240,
       
     7     x = d3.scale.linear().domain([0, n]).range([h, w - h]),
       
     8     a = d3.scale.linear().domain([0, n - 1]).range([90 + 60, 270 - 60]),
       
     9     data = shuffle(d3.range(n)),
       
    10     duration = 250;
       
    11 
       
    12 var vis = d3.select("#chart").append("svg:svg")
       
    13     .attr("width", w)
       
    14     .attr("height", h);
       
    15 
       
    16 var line = vis.selectAll("line")
       
    17     .data(data)
       
    18   .enter().append("svg:line")
       
    19     .attr("x1", 0)
       
    20     .attr("y1", 0)
       
    21     .attr("x2", 0)
       
    22     .attr("y2", h)
       
    23     .attr("transform", transform);
       
    24 
       
    25 start();
       
    26 
       
    27 // Start the animation!
       
    28 function start() {
       
    29   var passes = mergesort(data).reverse();
       
    30 
       
    31   update();
       
    32 
       
    33   function update() {
       
    34     var pass = passes.pop();
       
    35 
       
    36     line.data(pass, Number)
       
    37       .transition()
       
    38         .duration(duration)
       
    39         .attr("transform", transform);
       
    40 
       
    41     if (passes.length) {
       
    42       setTimeout(update, duration);
       
    43     } else {
       
    44       shuffle(data);
       
    45       setTimeout(start, duration + 4000);
       
    46     }
       
    47   }
       
    48 }
       
    49 
       
    50 function transform(d, i) {
       
    51   return "translate(" + x(i) + "," + h + ")rotate(" + a(d) + ")";
       
    52 }
       
    53 
       
    54 // Fisher-Yates shuffle
       
    55 function shuffle(array) {
       
    56   var i = array.length, j, t;
       
    57   while (--i > 0) {
       
    58     j = ~~(Math.random() * (i + 1));
       
    59     t = array[j];
       
    60     array[j] = array[i];
       
    61     array[i] = t;
       
    62   }
       
    63   return array;
       
    64 }
       
    65 
       
    66 //
       
    67 // Sorts the specified array using bottom-up mergesort, returning an array of
       
    68 // arrays representing the state of the specified array after each insertion for
       
    69 // each parallel pass. The first pass is performed at size = 2.
       
    70 //
       
    71 function mergesort(array) {
       
    72   var passes = [],
       
    73       i,
       
    74       j,
       
    75       n = array.length,
       
    76       m = 1;
       
    77 
       
    78   // double the size each pass
       
    79   while (m < array.length) {
       
    80     i = j = 0; while (i < array.length) j += merge(i, i += m, i += m);
       
    81     if (j) passes.push(array.slice());
       
    82     else m <<= 1;
       
    83   }
       
    84 
       
    85   // Merges two adjacent sorted arrays in-place.
       
    86   function merge(start, middle, end) {
       
    87     middle = Math.min(array.length, middle);
       
    88     end = Math.min(array.length, end);
       
    89     for (; start < middle; start++) {
       
    90       if (array[start] > array[middle]) {
       
    91         var v = array[start];
       
    92         array[start] = array[middle];
       
    93         insert(middle, end, v);
       
    94         return true;
       
    95       }
       
    96     }
       
    97     return false;
       
    98   }
       
    99 
       
   100   // Inserts the value v into the subarray specified by start and end.
       
   101   function insert(start, end, v) {
       
   102     while (start + 1 < end && array[start + 1] < v) {
       
   103       var tmp = array[start];
       
   104       array[start] = array[start + 1];
       
   105       array[start + 1] = tmp;
       
   106       start++;
       
   107     }
       
   108     array[start] = v;
       
   109   }
       
   110 
       
   111   return passes;
       
   112 }