parent
f2891359ab
commit
b224562970
8 changed files with 329 additions and 297 deletions
@ -0,0 +1,146 @@ |
||||
/** |
||||
* |
||||
*/ |
||||
var Itemgroup = { |
||||
/** |
||||
* |
||||
*/ |
||||
items: function items(group, delay, n) { |
||||
var g; |
||||
var all = []; |
||||
|
||||
// Items start with no background by default.
|
||||
for (var i = 0; i < n; i++) { |
||||
g = group.append('g') |
||||
.attr('class', `i${i}`) |
||||
.attr('transform', function transform(d) { |
||||
return `translate(${i * (Visualizer.itemW + Visualizer.spacerW) + Visualizer.padding}, ${Visualizer.padding})`; |
||||
});; |
||||
|
||||
g.append('rect') |
||||
.attr('class', 'item') |
||||
.attr('height', Visualizer.itemH) |
||||
.attr('width', Visualizer.itemW) |
||||
.attr('fill', 'transparent'); |
||||
|
||||
// Item labels
|
||||
g.append('text') |
||||
.attr('fill', '#aaa') |
||||
.attr('font-size', 10) |
||||
.attr('font-family', 'sans-serif') |
||||
.attr('transform', function transform(d) { |
||||
return `rotate(90 0,0), translate(5, -3)`; |
||||
}); |
||||
|
||||
all.push(g); |
||||
}; |
||||
|
||||
return all; |
||||
}, |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
swap: function swap(group, delay, indexA, indexB) { |
||||
var x, a, b; |
||||
var len = group.selectAll('g')[0].length; |
||||
|
||||
// NOTE pitfalls in the swapping problem.
|
||||
// NOTE Two way binding here between dataset and function parameter?
|
||||
// NOTE swapping will not reorder index and i parameter will be off
|
||||
// NOTE discuss chained transitions: http://bl.ocks.org/mbostock/1125997
|
||||
|
||||
// Animate a node swap which will be quietly undone after completion.
|
||||
group.selectAll('g').transition().duration(delay - 100) |
||||
.attr('transform', function transform(d, i) { |
||||
x = i * (Visualizer.itemW + Visualizer.spacerW) + Visualizer.padding; |
||||
|
||||
if (i === indexA) { |
||||
x = indexB * (Visualizer.itemW + Visualizer.spacerW) + Visualizer.padding; |
||||
a = d3.select(this).select('text').text(); |
||||
} |
||||
else if (i === indexB) { |
||||
x = indexA * (Visualizer.itemW + Visualizer.spacerW) + Visualizer.padding; |
||||
b = d3.select(this).select('text').text(); |
||||
|
||||
} |
||||
|
||||
return `translate(${x}, ${Visualizer.padding})`; |
||||
}) |
||||
.each('end', function(d, i) { |
||||
if (i !== len - 1) { |
||||
return; |
||||
} |
||||
|
||||
console.log(`indexA: ${indexA}, ${a}, indexB: ${indexB}, ${b}`); |
||||
|
||||
// Undo the animation by restoring the original positions and swapping the values.
|
||||
group.selectAll('g') |
||||
.attr('transform', function transform(d, i) { |
||||
x = i * (Visualizer.itemW + Visualizer.spacerW) + Visualizer.padding; |
||||
return `translate(${x}, ${Visualizer.padding})`; |
||||
}) |
||||
.each(function(d, i) { |
||||
if (i === indexA) { |
||||
d3.select(this).select('text').text(b); |
||||
} |
||||
else if (i === indexB) { |
||||
d3.select(this).select('text').text(a); |
||||
} |
||||
}); |
||||
|
||||
console.warn(`indexA: ${indexA}, ${a}, indexB: ${indexB}, ${b}`); |
||||
}); |
||||
}, |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
background: function background(group, delay, start, end, color) { |
||||
group.selectAll('g').each(function(d, i) { |
||||
if (i >= start && i <= end) { |
||||
d3.select(this).select('rect').attr('fill', color); |
||||
} |
||||
}); |
||||
}, |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
foreground: function foreground(group, delay, start, end, color) { |
||||
group.selectAll('g').each(function(d, i) { |
||||
if (i >= start && i <= end) { |
||||
d3.select(this).select('text').attr('fill', color); |
||||
} |
||||
}); |
||||
}, |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
text: function text(group, delay, which, text) { |
||||
// NOTE http://stackoverflow.com/questions/28390754/get-one-element-from-d3js-selection-by-index
|
||||
group.selectAll('g') |
||||
.filter(function filter(d, i) { return i === which; }) |
||||
.select('text').text(text); |
||||
}, |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
opacity: function opacity(group, delay, start, end, opacity) { |
||||
group.selectAll('g').each(function(d, i) { |
||||
if (i >= start && i <= end) { |
||||
d3.select(this).attr('opacity', opacity); |
||||
} |
||||
}); |
||||
}, |
||||
|
||||
/** |
||||
* Message updates. |
||||
*/ |
||||
message: function message(group, delay, which, msg) { |
||||
var msg = msg || ' '; |
||||
this.parent.querySelector(`.message:nth-child(${which})`).innerHTML = msg; |
||||
}, |
||||
}; |
@ -1,122 +0,0 @@ |
||||
/** |
||||
* |
||||
*/ |
||||
Visualizer.prototype.swap = function(delay, indexA, indexB) { |
||||
// NOTE Two way binding here between dataset and function parameter?
|
||||
// NOTE swapping will not reorder index and i parameter will be off
|
||||
// NOTE discuss chained transitions: http://bl.ocks.org/mbostock/1125997
|
||||
this.groups |
||||
.transition().duration(delay) |
||||
.attr('transform', function doTransform(d) { |
||||
if (d.index === indexA) { |
||||
d.index = indexB; |
||||
} |
||||
else if (d.index === indexB) { |
||||
d.index = indexA; |
||||
} |
||||
|
||||
return `translate(${Visualizer.calculateX(d.index)}, ${Visualizer.itemY})`; |
||||
}); |
||||
}; |
||||
|
||||
/** |
||||
* Highlights a range of indices with a color. End index and color optional. |
||||
*/ |
||||
Visualizer.prototype.highlight = function(delay, startIndex, endIndex, color) { |
||||
if (endIndex === undefined) { |
||||
endIndex = startIndex; |
||||
} |
||||
|
||||
if (color === undefined) { |
||||
color = 'orangered'; |
||||
} |
||||
|
||||
this.groups.each(function(d, i) { |
||||
if (d.index >= startIndex && d.index <= endIndex) { |
||||
d3.select(this).select('rect').attr('fill', color); |
||||
} |
||||
}); |
||||
}; |
||||
|
||||
/** |
||||
* Un-highlights an index. |
||||
*/ |
||||
Visualizer.prototype.unhighlight = function() { |
||||
// this.svg.selectAll('.item').attr('fill', function(d) { return d.fill; });
|
||||
this.svg.selectAll('.item').attr('fill', '#1A45AC'); |
||||
}; |
||||
|
||||
/** |
||||
* Greys out an item. |
||||
*/ |
||||
Visualizer.prototype.fade = function(delay, startIndex, endIndex) { |
||||
this.groups.each(function(d) { |
||||
if (d.index >= startIndex && d.index <= endIndex) { |
||||
d3.select(this).style('opacity', '0.2'); |
||||
} |
||||
}); |
||||
}; |
||||
|
||||
/** |
||||
* Restores all items to un-greyed state. |
||||
*/ |
||||
Visualizer.prototype.unfade = function() { |
||||
this.groups.each(function(d) { |
||||
d3.select(this).style('opacity', 1); |
||||
}); |
||||
}; |
||||
|
||||
/** |
||||
* Message updates. |
||||
*/ |
||||
Visualizer.prototype.message = function(delay, which, msg) { |
||||
var msg = msg || ' '; |
||||
this.parent.querySelector(`.message:nth-child(${which})`).innerHTML = msg; |
||||
}; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
Visualizer.prototype.item = function(delay, classname, x, y, text, color) { |
||||
var g = this.svg.append('g') |
||||
.attr('class', classname) |
||||
.attr('transform', `translate(${x}, ${y})`); |
||||
|
||||
g.append('rect').attr('width', Visualizer.itemW) |
||||
.attr('height', Visualizer.itemH) |
||||
.attr('fill', color); |
||||
|
||||
g.append('text').text(text) |
||||
.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)`; |
||||
}); |
||||
}; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
Visualizer.prototype.removeSecondary = function() { |
||||
this.svg.selectAll('.secondary').remove(); |
||||
}; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
Visualizer.prototype.removeTertiary = function() { |
||||
this.svg.selectAll('.tertiary').remove(); |
||||
}; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
Visualizer.prototype.remove = function(delay, id) { |
||||
this.svg.select(`#${id}`).remove(); |
||||
}; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
// Visualizer.prototype.move = function()
|
Loading…
Reference in new issue