|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<style> |
|
|
|
.controls { |
|
text-align: center; |
|
} |
|
|
|
.countdown { |
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; |
|
font-size: 48px; |
|
font-weight: bold; |
|
} |
|
|
|
.red { |
|
fill: red; |
|
} |
|
|
|
.blue { |
|
fill: blue; |
|
} |
|
|
|
</style> |
|
<body> |
|
<div class="controls"> |
|
</div> |
|
<script src="http://d3js.org/d3.v3.min.js"></script> |
|
<script> |
|
var controls = [ |
|
{ name: 'Static', action: staticItems }, |
|
{ name: 'Vertical Motion', action: movingItems }, |
|
{ name: 'Oscillation', action: oscillatingItems } |
|
]; |
|
|
|
var RED_SQUARES = 30; |
|
var BLUE_CIRCLES = 30; |
|
var CIRCLE_RADIUS = 10; |
|
var SQUARE_SIZE = Math.sqrt(Math.PI * CIRCLE_RADIUS * CIRCLE_RADIUS) |
|
|
|
var margin = {top: 40, right: 40, bottom: 40, left: 40}, |
|
width = 960 - margin.left - margin.right, |
|
height = 480 - margin.top - margin.bottom; |
|
|
|
var xScale = d3.scale.linear() |
|
.range([0, width]); |
|
|
|
var yScale = d3.scale.linear() |
|
.range([0, height]); |
|
|
|
var svg = d3.select("body").append("svg") |
|
.attr("width", width + margin.left + margin.right) |
|
.attr("height", height + margin.top + margin.bottom) |
|
.append("g") |
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); |
|
|
|
var shapes = svg.append('g'); |
|
var reds = shapes.append('g').attr('class', 'red'); |
|
var blues = shapes.append('g').attr('class', 'blue'); |
|
|
|
var countdown = svg.append("g") |
|
.attr("transform", "translate(" + width / 2 + ", " + height / 2 + ")") |
|
.append("text") |
|
.attr("text-anchor", "middle") |
|
.attr("class", "countdown"); |
|
|
|
function display(text) { |
|
reds.html("").interrupt(); |
|
blues.html("").interrupt(); |
|
countdown.text(text); |
|
} |
|
function countDown(start) { |
|
display("Find the red circle"); |
|
setTimeout(display, 2000, "3"); |
|
setTimeout(display, 3000, "2"); |
|
setTimeout(display, 4000, "1"); |
|
setTimeout(display, 5000, ""); |
|
setTimeout(start, 5000); |
|
} |
|
|
|
// Build the controls |
|
d3.select('.controls').selectAll('button') |
|
.data(controls) |
|
.enter() |
|
.append('button') |
|
.text(function (d) { return d.name; }) |
|
.on('click', function (d) { |
|
countDown(d.action); |
|
}); |
|
|
|
// Render the circles/squares randomly |
|
function draw() { |
|
reds.attr('transform', 'translate(0,0)'); |
|
blues.attr('transform', 'translate(0,0)'); |
|
var start = new Date().getTime(); |
|
var redSquares = d3.range(0, RED_SQUARES).map(function () { |
|
return { |
|
x: xScale(Math.random()), |
|
y: yScale(Math.random()) |
|
}; |
|
}); |
|
reds.selectAll('rect') |
|
.data(redSquares) |
|
.enter() |
|
.append('rect') |
|
.attr('x', function (d) { return d.x; }) |
|
.attr('y', function (d) { return d.y; }) |
|
.attr('width', SQUARE_SIZE) |
|
.attr('height', SQUARE_SIZE); |
|
|
|
var blueCircles = d3.range(0, BLUE_CIRCLES).map(function () { |
|
return { |
|
x: xScale(Math.random()), |
|
y: yScale(Math.random()) |
|
}; |
|
}); |
|
blues.selectAll('circle') |
|
.data(blueCircles) |
|
.enter() |
|
.append('circle') |
|
.attr('cx', function (d) { return d.x; }) |
|
.attr('cy', function (d) { return d.y; }) |
|
.attr('r', CIRCLE_RADIUS); |
|
|
|
// The magic red circle |
|
reds.append('circle') |
|
.datum(function () { return { x: xScale(Math.random()), y: yScale(Math.random())}; }) |
|
.attr('cx', function (d) { return d.x; }) |
|
.attr('cy', function (d) { return d.y; }) |
|
.attr('r', CIRCLE_RADIUS) |
|
.on('click', function () { |
|
var end = new Date().getTime(); |
|
var took = end - start; |
|
display("Took " + took + "ms"); |
|
}); |
|
} |
|
|
|
// Simple case, all items stationary |
|
function staticItems() { |
|
draw(); |
|
} |
|
|
|
// Red items move up, blue move down |
|
function movingItems() { |
|
draw(); |
|
reds.transition().duration(3000).ease("linear") |
|
.attr('transform', 'translate(0,-40)'); |
|
blues.transition().duration(3000).ease("linear") |
|
.attr('transform', 'translate(0,40)'); |
|
} |
|
|
|
// Red oscillate up/down, blue oscillate left/right |
|
function oscillatingItems() { |
|
draw(); |
|
|
|
function stateA() { |
|
reds.transition().duration(500) |
|
.attr('transform', 'translate(0,20)') |
|
.each('end', stateB); |
|
blues.transition().duration(500).delay(500) |
|
.attr('transform', 'translate(20,0)'); |
|
} |
|
function stateB() { |
|
reds.transition().duration(500) |
|
.attr('transform', 'translate(0,0)') |
|
.each('end', stateA); |
|
blues.transition().duration(500).delay(500) |
|
.attr('transform', 'translate(0,0)'); |
|
} |
|
stateA(); |
|
} |
|
</script> |
|
</body> |