An example of snapping elements to a grid on drag.
References:
license: MIT |
An example of snapping elements to a grid on drag.
References:
<!doctype html> | |
<style> | |
svg { | |
box-sizing: border-box; | |
border: 1px solid rgb(212, 212, 212); | |
} | |
circle { | |
stroke: rgb(95, 176, 228); | |
stroke-width: 2; | |
fill: rgba(205, 246, 255, 0.3); | |
} | |
line { | |
stroke: rgb(212, 212, 212); | |
stroke-width: 1px; | |
shape-rendering: crispEdges; | |
} | |
</style> | |
<body> | |
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<script> | |
var width = 960, | |
height = 500, | |
resolution = 20, | |
r = 15; | |
var points = d3.range(10).map(function() { | |
return { | |
x: round(Math.random() * width, resolution), | |
y: round(Math.random() * height, resolution) | |
}; | |
}); | |
var drag = d3.behavior.drag() | |
.origin(function(d) { return d; }) | |
.on('drag', dragged); | |
var svg = d3.select('body').append('svg') | |
.attr('width', width) | |
.attr('height', height); | |
svg.selectAll('.vertical') | |
.data(d3.range(1, width / resolution)) | |
.enter().append('line') | |
.attr('class', 'vertical') | |
.attr('x1', function(d) { return d * resolution; }) | |
.attr('y1', 0) | |
.attr('x2', function(d) { return d * resolution; }) | |
.attr('y2', height); | |
svg.selectAll('.horizontal') | |
.data(d3.range(1, height / resolution)) | |
.enter().append('line') | |
.attr('class', 'horizontal') | |
.attr('x1', 0) | |
.attr('y1', function(d) { return d * resolution; }) | |
.attr('x2', width) | |
.attr('y2', function(d) { return d * resolution; }); | |
var circles = svg.selectAll('circle') | |
.data(points) | |
.enter().append('circle') | |
.attr('cx', function(d) { return d.x; }) | |
.attr('cy', function(d) { return d.y; }) | |
.attr('r', r) | |
.call(drag); | |
function dragged(d) { | |
var x = d3.event.x, | |
y = d3.event.y, | |
gridX = round(Math.max(r, Math.min(width - r, x)), resolution), | |
gridY = round(Math.max(r, Math.min(height - r, y)), resolution); | |
d3.select(this).attr('cx', d.x = gridX).attr('cy', d.y = gridY); | |
} | |
function round(p, n) { | |
return p % n < n / 2 ? p - (p % n) : p + n - (p % n); | |
} | |
</script> | |
</body> |