Click-hold to select geographic units whose centroids are within the circular area surrounding the cursor.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Circular Geography Selection</title>
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: auto;
position: relative;
width: 960px;
}
button {
position: absolute;
right: 10px;
top: 10px;
}
canvas {
cursor: crosshair;
}
</style>
</head>
<body>
<button class="reset">Reset</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
<script>
var width = 960,
height = 500,
clickRadius = 4;
var projection = d3.geo.albers()
.scale(1000);
var canvas = d3.select("body").append("canvas")
.attr('width', width)
.attr('height', height);
var context = canvas.node().getContext('2d');
var path = d3.geo.path()
.projection(projection)
.context(context);
var button = d3.select("button.reset");
d3.json('us.json', function(error, us) {
if (error) throw error;
var counties = topojson.feature(us, us.objects.counties);
counties.features.forEach(function(feature) {
feature.properties.centroid = path.centroid(feature);
});
path(counties);
context.fillStyle = "#a3c1ad";
context.fill();
context.strokeStyle = "#fff";
context.lineWidth = .5;
context.stroke();
button
.on('click', function() {
path(counties);
context.fillStyle = "#a3c1ad";
context.fill();
context.stroke();
});
canvas
.on('mousemove', function() {
var e = d3.event,
cx = e.layerX,
cy = e.layerY;
if (e.buttons == 1) {
var featuresInRadius = counties.features.filter(function(feature) {
var centroid = feature.properties.centroid,
x = centroid[0],
y = centroid[1];
return Math.sqrt(Math.pow(x - cx, 2) + Math.pow(y - cy, 2))
<= Math.pow(clickRadius, 2);
});
featuresInRadius = {
type: "FeatureCollection",
features: featuresInRadius
};
context.beginPath();
path(featuresInRadius);
context.fillStyle = "#5f9ea0";
context.fill();
context.stroke();
}
});
});
</script>
</body>
</html>