This example demonstrates using d3.drag with d3.forceCollide to implement draggable circles with collision detection.
Last active
September 21, 2017 11:37
-
-
Save mbostock/2990a882e007f8384b04827617752738 to your computer and use it in GitHub Desktop.
Force Dragging II
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<canvas width="960" height="500"></canvas> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script> | |
var canvas = document.querySelector("canvas"), | |
context = canvas.getContext("2d"), | |
width = canvas.width, | |
height = canvas.height, | |
radius = 20; | |
var circles = d3.range(324).map(function(i) { | |
return { | |
x: (i % 25) * (radius + 1) * 2, | |
y: Math.floor(i / 25) * (radius + 1) * 2 | |
}; | |
}); | |
var simulation = d3.forceSimulation(circles) | |
.force("collide", d3.forceCollide(radius + 1).iterations(4)) | |
.on("tick", drawCircles); | |
d3.select(canvas) | |
.call(d3.drag() | |
.container(canvas) | |
.subject(dragsubject) | |
.on("start", dragstarted) | |
.on("drag", dragged) | |
.on("end", dragended)); | |
function drawCircles() { | |
context.clearRect(0, 0, width, height); | |
context.save(); | |
context.beginPath(); | |
circles.forEach(drawCircle); | |
context.fill(); | |
context.strokeStyle = "#fff"; | |
context.stroke(); | |
} | |
function drawCircle(d) { | |
context.moveTo(d.x + radius, d.y); | |
context.arc(d.x, d.y, radius, 0, 2 * Math.PI); | |
} | |
function dragsubject() { | |
return simulation.find(d3.event.x, d3.event.y, radius); | |
} | |
function dragstarted() { | |
if (!d3.event.active) simulation.alphaTarget(0.3).restart(); | |
d3.event.subject.fx = d3.event.subject.x; | |
d3.event.subject.fy = d3.event.subject.y; | |
} | |
function dragged() { | |
d3.event.subject.fx = d3.event.x; | |
d3.event.subject.fy = d3.event.y; | |
} | |
function dragended() { | |
if (!d3.event.active) simulation.alphaTarget(0); | |
d3.event.subject.fx = null; | |
d3.event.subject.fy = null; | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment