block by armollica 94bfb37d81234ad91ced

Circular Geography Selection

Full Screen

Click-hold to select geographic units whose centroids are within the circular area surrounding the cursor.

index.html

<!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>