|
(function(d3) { |
|
'use strict' |
|
var height, |
|
width, |
|
count, |
|
duration, |
|
array, |
|
columns, |
|
parameters, |
|
grid, |
|
scales, |
|
svg, |
|
control, |
|
slider, |
|
item, |
|
loop, |
|
factory, |
|
shape, |
|
collect |
|
height = 500 |
|
width = 960 |
|
count = 200 |
|
duration = 1000 |
|
array = Array.apply(this, {length: count}) |
|
// store variable names in a single data structure |
|
// so we can work with them programmatically |
|
parameters = { |
|
'hue': [0, 360], |
|
'saturation': [0, 1], |
|
'lightness': [0, 1], |
|
'opacity': [0, 1], |
|
'rotation': [-360, 360], |
|
'skew': [-360, 360], |
|
'size': [0, 2] |
|
} |
|
columns = Object.keys(parameters).length |
|
grid = width / columns |
|
scales = {} |
|
Object.keys(parameters).forEach(function(parameter) { |
|
var scale |
|
scale = d3.scaleLinear() |
|
.domain([height, 0]) |
|
.range(parameters[parameter]) |
|
scales[parameter] = scale |
|
}) |
|
factory = function() { |
|
var f, |
|
hue, |
|
saturation, |
|
lightness, |
|
opacity, |
|
rotation = 0, |
|
skew = 0, |
|
size = 0 |
|
f = function(selection) { |
|
var color, |
|
transform |
|
color = d3.hsl(hue, saturation, lightness, opacity) |
|
transform = 'rotate(' + rotation + ')skewX(' + skew + ')scale(' + size + ')' |
|
selection |
|
.append('rect') |
|
.style('fill', color.toString()) |
|
.style('stroke', 'black') |
|
.attr('height', 0) |
|
.attr('width', 0) |
|
.transition('rotate') |
|
.duration(duration) |
|
.attr('transform', transform) |
|
} |
|
// configuration methods |
|
f.hue = _ => _ !== undefined ? (hue = _, f) : hue |
|
f.saturation = _ => _ !== undefined ? (saturation = _, f) : saturation |
|
f.lightness = _ => _ !== undefined ? (lightness = _, f) : lightness |
|
f.opacity = _ => _ !== undefined ? (opacity = _, f) : opacity |
|
f.rotation = _ => _ !== undefined ? (rotation = _, f) : rotation |
|
f.skew = _ => _ !== undefined ? (skew = _, f) : skew |
|
f.size = _ => _ !== undefined ? (size = _, f) : size |
|
return f |
|
} |
|
shape = factory() |
|
svg = d3.select('div.target') |
|
.append('svg') |
|
.attr('height', height) |
|
.attr('width', width) |
|
item = svg.append('g') |
|
.classed('items', true) |
|
.attr('transform', 'translate(' + grid * 0.5 + ',0)') |
|
.selectAll('g.item') |
|
.data(array) |
|
.enter() |
|
.append('g') |
|
.classed('item', true) |
|
item.attr('transform', function(d, i) { |
|
var x, |
|
y |
|
x = i % columns * grid |
|
y = Math.floor(i / columns) * grid |
|
return 'translate(' + x + ',' + y + ')' |
|
}) |
|
slider = function(selection) { |
|
var slider_width, |
|
x_offset |
|
slider_width = grid |
|
x_offset = (grid - slider_width) * 0.5 |
|
selection.append('rect') |
|
.attr('x', x_offset) |
|
.attr('height', 10) |
|
.attr('width', slider_width) |
|
.style('stroke', 'white') |
|
.style('stroke-width', 3) |
|
} |
|
control = svg.append('g') |
|
.classed('controls', true) |
|
.selectAll('g.control') |
|
.data(Object.keys(parameters)) |
|
.enter() |
|
.append('g') |
|
.attr('class', 'control') |
|
.attr('data-control', function(d) { |
|
return d |
|
}) |
|
.attr('transform', function(d, i) { |
|
var x |
|
x = grid * i |
|
return 'translate(' + x + ',0)' |
|
}) |
|
control |
|
.append('g') |
|
.classed('slider', true) |
|
.each(function() { |
|
d3.select(this).call(slider) |
|
}) |
|
control |
|
.append('rect') |
|
.attr('height', height) |
|
.attr('width', grid) |
|
.style('opacity', 0) |
|
control |
|
.append('text') |
|
.classed('label', true) |
|
.attr('transform', 'translate(' + (grid * 0.5) + ',' + (height * 0.5) + ') rotate(270)') |
|
.text(function(d) { |
|
return d.replace(/_/g, ' ') |
|
}) |
|
control.on('mousemove', function() { |
|
var new_y |
|
new_y = d3.mouse(this)[1] |
|
d3.select(this).select('g.slider rect') |
|
.transition() |
|
.ease(d3.easeLinear) |
|
.attr('y', new_y) |
|
}) |
|
collect = function() { |
|
control.each(function(d) { |
|
var y, |
|
value |
|
y = d3.select(this).select('g.slider rect') |
|
.node() |
|
.getBBox() |
|
.y |
|
value = scales[d](y) |
|
if (typeof shape[d] === 'function') { |
|
shape[d](value) |
|
} |
|
}) |
|
} |
|
loop = function(selection) { |
|
collect() |
|
selection |
|
.call(shape) |
|
.select('rect') |
|
.transition('change') |
|
.duration(duration) |
|
.delay(function(d, i) { |
|
return duration / count * i |
|
}) |
|
.attr('height', grid) |
|
.attr('width', grid) |
|
.transition('remove') |
|
.duration(duration) |
|
.attr('height', 0) |
|
.attr('width', 0) |
|
.remove() |
|
} |
|
item.call(loop) |
|
setInterval(function() { |
|
item.selectAll('rect').remove() |
|
item.call(loop) |
|
}, duration * 3) |
|
}).call(this, d3) |