block by nitaku c8a4e63b4da8bc4ac51e162f742f3b87

Voronoi

Full Screen

A reference implementation of a Voronoi diagram in d3 v4.

index.js

// Generated by CoffeeScript 1.10.0
(function() {
  var cells, cells_data, height, radius, sites, sites_data, svg, voronoi, width;

  svg = d3.select('svg');

  width = svg.node().getBoundingClientRect().width;

  height = svg.node().getBoundingClientRect().height;

  radius = 10;

  sites_data = d3.range(20).map(function() {
    return {
      x: Math.round(Math.random() * (width - radius * 2) + radius),
      y: Math.round(Math.random() * (height - radius * 2) + radius)
    };
  });

  voronoi = d3.voronoi().x(function(d) {
    return d.x;
  }).y(function(d) {
    return d.y;
  }).extent([[-1, -1], [width + 1, height + 1]]);

  cells_data = voronoi.polygons(sites_data);

  cells = svg.selectAll('.cell').data(cells_data);

  cells.enter().append('path').attrs({
    "class": 'cell',
    d: function(d) {
      if (d == null) {
        return null;
      } else {
        return "M" + d.join("L") + "Z";
      }
    }
  });

  sites = svg.selectAll('.site').data(sites_data);

  sites.enter().append('circle').attrs({
    "class": 'site',
    r: radius,
    cx: function(d) {
      return d.x;
    },
    cy: function(d) {
      return d.y;
    }
  });

}).call(this);

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Voronoi</title>
  <link type="text/css" href="index.css" rel="stylesheet"/>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script src="https://d3js.org/d3-selection-multi.v0.4.min.js"></script>
</head>
<body>
  <svg></svg>
  <script src="index.js"></script>
</body>
</html>

index.coffee

svg = d3.select 'svg'
width = svg.node().getBoundingClientRect().width
height = svg.node().getBoundingClientRect().height
    
radius = 10

sites_data = d3.range(20).map () ->
  return {
    x: Math.round(Math.random() * (width - radius * 2) + radius),
    y: Math.round(Math.random() * (height - radius * 2) + radius)
  }

voronoi = d3.voronoi()
  .x (d) -> d.x
  .y (d) -> d.y
  .extent [[-1, -1], [width + 1, height + 1]]
  
cells_data = voronoi.polygons(sites_data)

# render cells
cells = svg.selectAll '.cell'
  .data cells_data
  
cells.enter().append 'path'
  .attrs
    class: 'cell'
    d: (d) ->  if not d? then null else "M" + d.join("L") + "Z"


# render sites
sites = svg.selectAll '.site'
  .data sites_data
  
sites.enter().append 'circle'
  .attrs
    class: 'site'
    r: radius
    cx: (d) -> d.x
    cy: (d) -> d.y
    

index.css

body, html {
  padding: 0;
  margin: 0;
  height: 100%;
}
svg {
  width: 100%;
  height: 100%;
  background: white;
}

.site {
  fill: #DDD;
  stroke: gray;
}
.cell {
  fill: none;
  stroke: #777;
  stroke-width: 1;
}