|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<canvas width="960" height="500"></canvas> |
|
<script src="//d3js.org/d3.v4.min.js"></script> |
|
<script> |
|
|
|
var canvas = d3.select("canvas"), |
|
context = canvas.node().getContext("2d"), |
|
width = canvas.property("width"), |
|
height = canvas.property("height"), |
|
radius = 32; |
|
|
|
var circles = d3.range(20).map(function(i) { |
|
return { |
|
index: i, |
|
x: Math.round(Math.random() * (width - radius * 2) + radius), |
|
y: Math.round(Math.random() * (height - radius * 2) + radius) |
|
}; |
|
}); |
|
|
|
var color = d3.scaleOrdinal() |
|
.range(d3.schemeCategory20); |
|
|
|
render(); |
|
|
|
canvas.call(d3.drag() |
|
.subject(dragsubject) |
|
.on("start", dragstarted) |
|
.on("drag", dragged) |
|
.on("end", dragended) |
|
.on("start.render drag.render end.render", render)); |
|
|
|
function render() { |
|
context.clearRect(0, 0, width, height); |
|
for (var i = 0, n = circles.length, circle; i < n; ++i) { |
|
circle = circles[i]; |
|
context.beginPath(); |
|
context.moveTo(circle.x + radius, circle.y); |
|
context.arc(circle.x, circle.y, radius, 0, 2 * Math.PI); |
|
context.fillStyle = color(circle.index); |
|
context.fill(); |
|
if (circle.active) { |
|
context.lineWidth = 2; |
|
context.stroke(); |
|
} |
|
} |
|
} |
|
|
|
function dragsubject() { |
|
var i = 0, |
|
n = circles.length, |
|
dx, |
|
dy, |
|
d2, |
|
s2 = radius * radius * 4, // Double the radius. |
|
circle, |
|
subject; |
|
|
|
for (i = 0; i < n; ++i) { |
|
circle = circles[i]; |
|
dx = d3.event.x - circle.x; |
|
dy = d3.event.y - circle.y; |
|
d2 = dx * dx + dy * dy; |
|
if (d2 < s2) subject = circle, s2 = d2; |
|
} |
|
|
|
return subject; |
|
} |
|
|
|
function dragstarted() { |
|
circles.splice(circles.indexOf(d3.event.subject), 1); |
|
circles.push(d3.event.subject); |
|
d3.event.subject.active = true; |
|
} |
|
|
|
function dragged() { |
|
d3.event.subject.x = d3.event.x; |
|
d3.event.subject.y = d3.event.y; |
|
} |
|
|
|
function dragended() { |
|
d3.event.subject.active = false; |
|
} |
|
|
|
</script> |