Skip to content

Instantly share code, notes, and snippets.

@Krzysztof-FF
Forked from patricksurry/README.md
Last active October 24, 2019 11:18
Show Gist options
  • Save Krzysztof-FF/f256cd1aef376c754934564e8595a208 to your computer and use it in GitHub Desktop.
Save Krzysztof-FF/f256cd1aef376c754934564e8595a208 to your computer and use it in GitHub Desktop.
SVG Snap - draw utilizing plain hover snap

This example modifies my own draw with nearest neighbor snap to draw polyline using snap to chosen point.
To make snap active, circle area around desired target point should be hovered by cursor position.
This example was created to examine feasibility of such idea.
Unfortunately, choosing between densely distributed points in some cases is almost impossible.
Going closer to desired points may not help, if area around other point in close proximity is hovered already.
Sometimes it is necessary to approach to desired point from some alternate direction so as not to activate other attraction areas.
To make this example feasible, I had to decrease distance tolerance to 10 (comparing to 20 in previous case).

<!DOCTYPE html>
<meta charset = "utf-8">
<title> SVG Snap - draw utilizing plain hover snap </title>
<style>
.point {
fill: #999;
stroke: # fff;
pointer-events: none;
}
.circle {
fill: white;
fill-opacity: 0;
stroke: lightgrey;
stroke-opacity: 0.5;
pointer-events: all;
}
.point.selected {
fill: red;
fill-opacity: 1;
}
.circle.selected {
stroke: red;
}
</style>
<body>
<script src = "http://d3js.org/d3.v3.min.js"></script>
<script>
var width = 960,
height = 500;
var RADIUS = 10;
var data = d3.range(400).map(function () {
return [Math.random() * width, Math.random() * height];
});
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.on("mousemove", function (d) {
var xy = d3.mouse(d3.selectAll('svg')[0][0]);
svg.select("#pt")
.attr("cx", xy[0])
.attr("cy", xy[1]);
mousemoved();
})
.on("click", function (d) {
sel = svg.select('.selected');
if (sel.empty()) {
sel = svg.select("#pt");
}
if (!sel.empty()) {
var x = sel.attr("cx");
var y = sel.attr("cy");
svg.select("#pt")
.attr("cx", x)
.attr("cy", y);
mousemoved();
poly.attr("points", poly.attr("points") + " " + x + "," + y);
}
});
svg.append("circle")
.attr("id", "pt")
.attr("r", 3)
.attr("cx", width / 2)
.attr("cy", height / 2)
.style("fill", "yellow");
var mouseCircle = svg.append("circle").classed("mouse", true)
.attr({
r: RADIUS,
fill: "none",
stroke: "#555"
});
var poly = svg.append("polyline")
.attr({
points: width / 2 + "," + height / 2 + " " + width / 2 + "," + height / 2,
fill: "none",
stroke: "gray"
});
var point = svg.selectAll(".point")
.data(data)
.enter().append("circle")
.attr("class", "point")
.attr("cx", function (d) {
return d[0];
})
.attr("cy", function (d) {
return d[1];
})
.attr("r", 3);
svg.selectAll(".point").each(function(d) {
var sibling = this.nextSibling;
var target = d3.select(this);
svg.insert("circle", function() { return sibling; })
.attr("class", "circle")
.attr("cx", function () {
return target.attr("cx");
})
.attr("cy", function () {
return target.attr("cy");
})
.attr("r", RADIUS)
.on("mouseover", function() {
d3.select(this).classed("selected", true);
d3.select(this.previousSibling).classed("selected", true);
mouseCircle.attr("stroke", "blue");
})
.on("mouseout", function() {
d3.select(this).classed("selected", false);
d3.select(this.previousSibling).classed("selected", false);
mouseCircle.attr("stroke", "gray");
})
;
});
function mousemoved() {
pt = svg.select('#pt');
var x = +pt.attr('cx'),
y = +pt.attr('cy');
mouseCircle.attr({
cx: x,
cy: y
});
var pp = poly.attr("points");
pp = pp.substring(0, pp.lastIndexOf(" ")) + " " + x + "," + y;
poly.attr("points", pp);
}
mousemoved();
</script>
<body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment