Skip to content

Instantly share code, notes, and snippets.

@Herst
Forked from mbostock/.block
Last active February 19, 2018 17:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Herst/3d486648556a3eee60442da977022fd1 to your computer and use it in GitHub Desktop.
Save Herst/3d486648556a3eee60442da977022fd1 to your computer and use it in GitHub Desktop.
Click vs. (a great deal of) Drag(ging)
license: gpl-3.0

Here .clickDistance() is used together with some manual checking to do certain stuff like calling .raise() only outside the distance otherwise the click event might not get triggered (because the element got removed from the DOM before release of the mouse button).

Related to https://bl.ocks.org/mbostock/22994cc97fefaeede0d861e6815a847e (this one it is based on), https://bl.ocks.org/mbostock/a84aeb78fea81e1ad806 (unlike that example this here allows for a tiny bit of movement → unstable clicks). See also the discussion at d3/d3-drag#48 to make the need for additional manual checking go away.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.active {
stroke: #000;
stroke-width: 2px;
}
</style>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var CLICK_DISTANCE = 4,
CLICK_DISTANCE_2 = CLICK_DISTANCE * CLICK_DISTANCE;
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
radius = 32;
var circles = d3.range(20).map(function() {
return {
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);
svg.selectAll("circle")
.data(circles)
.enter().append("circle")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", radius)
.style("fill", function(d, i) { return color(i); })
.on("click", clicked)
.call(d3.drag()
.clickDistance(CLICK_DISTANCE)
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
function dragstarted(d) {
d.startX = d3.event.sourceEvent.clientX;
d.startY = d3.event.sourceEvent.clientY;
}
function dragged(d) {
var e = d3.select(this),
dStartX = d.startX - d3.event.sourceEvent.clientX,
dStartY = d.startY - d3.event.sourceEvent.clientY;
if (dStartX * dStartX + dStartY * dStartY > CLICK_DISTANCE_2 &&
!e.classed("active")) {
e.raise().classed("active", true);
}
e.attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
}
function dragended(d) {
d3.select(this).classed("active", false);
}
function clicked(d) {
d3.select(this).transition()
.attr("r", 64)
.transition()
.attr("r", 32);
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment