|
|
|
@ -1,15 +1,16 @@ |
|
|
|
|
/** |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
var Visualizer = function() { |
|
|
|
|
this.itemW = 20; |
|
|
|
|
this.itemH = 50; |
|
|
|
|
var Visualizer = function() {}; |
|
|
|
|
|
|
|
|
|
this.svg = null; |
|
|
|
|
this.instructions = null; |
|
|
|
|
}; |
|
|
|
|
Visualizer.prototype.svg = null; |
|
|
|
|
Visualizer.prototype.instructions = null; |
|
|
|
|
Visualizer.spacerW = 5; |
|
|
|
|
Visualizer.itemW = 14; |
|
|
|
|
Visualizer.itemH = 50; |
|
|
|
|
Visualizer.itemY = 20; |
|
|
|
|
|
|
|
|
|
Visualizer.svg = null; |
|
|
|
|
Visualizer.groups = null; |
|
|
|
|
Visualizer.instructions = null; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* |
|
|
|
@ -24,22 +25,27 @@ Visualizer.prototype.init = function(data) { |
|
|
|
|
this.svg = d3.select('body').append('svg') |
|
|
|
|
.attr('class', 'quicksort-random'); |
|
|
|
|
|
|
|
|
|
this.svg.selectAll('rect').data(data).enter() |
|
|
|
|
.append('rect') |
|
|
|
|
.attr('height', function h(d) { return d.h; }) |
|
|
|
|
.attr('width', function w(d) { return d.w; }) |
|
|
|
|
.attr('fill', function fill(d) { return d.fill; }) |
|
|
|
|
.attr('y', function y(d) { return d.y; }) |
|
|
|
|
.attr('x', function x(d) { return d.x; }) |
|
|
|
|
.append('text') |
|
|
|
|
.text(function t(d) { return d.val; }) |
|
|
|
|
.attr('fill', '#000') |
|
|
|
|
.attr('x', function x(d) { return d.x; }) |
|
|
|
|
.transition(500) |
|
|
|
|
.attr('x', function expand(d, i) { |
|
|
|
|
data[i].x = i * (d.w + 2); |
|
|
|
|
return data[i].x; |
|
|
|
|
}); |
|
|
|
|
this.groups = this.svg.selectAll('g').data(data).enter().append('g') |
|
|
|
|
.attr('transform', `translate(0, ${Visualizer.itemY})`); |
|
|
|
|
|
|
|
|
|
this.groups.append('rect') |
|
|
|
|
.attr('height', Visualizer.itemH) |
|
|
|
|
.attr('width', Visualizer.itemW) |
|
|
|
|
.attr('fill', function doFill(d) { return d.fill; }); |
|
|
|
|
|
|
|
|
|
this.groups.transition(500) |
|
|
|
|
.attr('transform', function doTransform(d, i) { |
|
|
|
|
return `translate(${i * (Visualizer.itemW + Visualizer.spacerW)}, ${Visualizer.itemY})`; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
this.groups.append('text') |
|
|
|
|
.text(function t(d) { console.log(d.val); return d.val; }) |
|
|
|
|
.attr('fill', '#aaa') |
|
|
|
|
.attr('font-size', 10) |
|
|
|
|
.attr('font-family', 'sans-serif') |
|
|
|
|
.attr('transform', function doTransform(d) { |
|
|
|
|
return `rotate(90 0,0), translate(5, -3)`; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// this.svg.append('sometext').id('left-marker'); L
|
|
|
|
|
// this.svg.append('sometext').id('right-marker'); R
|
|
|
|
@ -53,46 +59,20 @@ Visualizer.prototype.swap = function(indexA, indexB) { |
|
|
|
|
// Move up
|
|
|
|
|
// NOTE Two way binding here between dataset and function parameter?
|
|
|
|
|
// NOTE swapping will not reorder index and i parameter will be off
|
|
|
|
|
this.svg.selectAll('rect') |
|
|
|
|
// .transition()
|
|
|
|
|
// .duration(100)
|
|
|
|
|
// .attr('y', function ya(d) {
|
|
|
|
|
// if (d.index === indexA || d.index === indexB) {
|
|
|
|
|
// d.y = 5;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// return d.y; // NOTE d[i].y has been modified too. But, the bound value in the dataset
|
|
|
|
|
// // will not be updated until after the chain is completed, so it has to be explicitly defined here.
|
|
|
|
|
// })
|
|
|
|
|
|
|
|
|
|
// Switch places
|
|
|
|
|
// NOTE discuss chained transitions: http://bl.ocks.org/mbostock/1125997
|
|
|
|
|
// TODO now that elements aren't cached, is there a need for .index?
|
|
|
|
|
.transition() |
|
|
|
|
.duration(400) |
|
|
|
|
.attr('x', function xa(d) { |
|
|
|
|
// NOTE discuss chained transitions: http://bl.ocks.org/mbostock/1125997
|
|
|
|
|
// TODO now that elements aren't cached, is there a need for .index?
|
|
|
|
|
this.groups |
|
|
|
|
.transition().duration(400) |
|
|
|
|
.attr('transform', function doTransform(d) { |
|
|
|
|
if (d.index === indexA) { |
|
|
|
|
d.index = indexB; |
|
|
|
|
d.x = d.index * (d.w + 2); |
|
|
|
|
} |
|
|
|
|
else if (d.index === indexB) { |
|
|
|
|
d.index = indexA; |
|
|
|
|
d.x = d.index * (d.w + 2); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return d.x; |
|
|
|
|
return `translate(${d.index * (Visualizer.itemW + Visualizer.spacerW)}, ${Visualizer.itemY})`; |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
// Move down
|
|
|
|
|
// .transition()
|
|
|
|
|
// .duration(100)
|
|
|
|
|
// .attr('y', function ya(d) {
|
|
|
|
|
// if (d.index === indexA || d.index === indexB) {
|
|
|
|
|
// d.y = 20;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// return d.y;
|
|
|
|
|
// });
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -106,18 +86,18 @@ Visualizer.prototype.moveMarker = function(id, toIndex) { |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
Visualizer.prototype.addMarker = function(id) { |
|
|
|
|
this.svg.append('text') |
|
|
|
|
.attr('id', id) |
|
|
|
|
.attr('x', 0) |
|
|
|
|
.attr('y', 10) |
|
|
|
|
.attr('width', 20) |
|
|
|
|
.attr('height', 20) |
|
|
|
|
.attr('fill', '#333') |
|
|
|
|
.attr('font-size', 20) |
|
|
|
|
.attr('alignment-baseline', 'middle') |
|
|
|
|
.attr('text-anchor', 'middle') |
|
|
|
|
.attr('transform', 'rotate(90 10,10)') |
|
|
|
|
.text('P'); |
|
|
|
|
// this.svg.append('text')
|
|
|
|
|
// .attr('id', id)
|
|
|
|
|
// .attr('x', 53)
|
|
|
|
|
// .attr('y', 50)
|
|
|
|
|
// .attr('width', 20)
|
|
|
|
|
// .attr('height', 20)
|
|
|
|
|
// .attr('fill', '#aaa')
|
|
|
|
|
// .attr('font-size', 20)
|
|
|
|
|
// .attr('alignment-baseline', 'middle')
|
|
|
|
|
// .attr('text-anchor', 'middle')
|
|
|
|
|
// .attr('transform', 'rotate(0 53,50)')
|
|
|
|
|
// .text('P');
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -152,7 +132,7 @@ Visualizer.prototype.unfade = function() { |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
Visualizer.prototype.followInstruction = function(instructions, index) { |
|
|
|
|
if (index >= instructions.length || index > 25) { |
|
|
|
|
if (index >= instructions.length) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -164,9 +144,9 @@ Visualizer.prototype.followInstruction = function(instructions, index) { |
|
|
|
|
setTimeout(this.followInstruction.bind(this, instructions, index + 1), 400); |
|
|
|
|
} |
|
|
|
|
else if (i.operation === 'init') { |
|
|
|
|
this.unfade(); |
|
|
|
|
this.fade(0, i.left - 1); |
|
|
|
|
this.fade(i.right + 1, 1000) |
|
|
|
|
// this.unfade();
|
|
|
|
|
// this.fade(0, i.left - 1);
|
|
|
|
|
// this.fade(i.right + 1, 1000)
|
|
|
|
|
this.followInstruction(instructions, index + 1); |
|
|
|
|
} |
|
|
|
|
else if (i.operation === 'swap') { |
|
|
|
|