block by wboykinm 3ba64baf9aa7121f4ff00bd2eb0c6e53

Papua coast histogram

Full Screen

Based on a fine arts example by Mike Bostock, but with satellite imagery from the dove flock. Imagery source: Planet Labs.

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<style>

canvas,
svg {
  position: absolute;
}

.brush .selection {
  stroke: #fff;
  stroke-opacity: 0.7;
  shape-rendering: crispEdges;
}

.histogram {
  pointer-events: none;
}

.histogram-panel {
  fill: #111;
  fill-opacity: 0.5;
  stroke: #000;
}

.histogram-area {
  mix-blend-mode: screen;
}

.histogram-area.histogram-r {
  fill: #f00;
}

.histogram-area.histogram-g {
  fill: #0f0;
}

.histogram-area.histogram-b {
  fill: #00f;
}

.histogram-line {
  fill: none;
  stroke: #000;
  stroke-width: 0.5px;
}

</style>
<canvas width="1200" height="700"></canvas>
<svg width="1200" height="700"></svg>
<script src="https://d3js.org/d3.v4.0.0-alpha.44.min.js"></script>
<script>

d3_color =
d3_dispatch =
d3_ease =
d3_interpolate =
d3_timer =
d3_selection =
d3_transition =
d3_drag = d3;

</script>
<script src="https://d3js.org/d3-brush.v0.1.min.js"></script>
<script>

var canvas = document.querySelector("canvas"),
    context = canvas.getContext("2d"),
    width = canvas.width,
    height = canvas.height;

var histomargin = {top: 10, right: 10, bottom: 0, left: width - 256 - 10},
    histowidth = width - histomargin.left - histomargin.right,
    histoheight = 256;

var r = d3.range(257).map(function() { return 0; }),
    g = d3.range(257).map(function() { return 0; }),
    b = d3.range(257).map(function() { return 0; }),
    x = function(d, i) { return i; },
    y = function(d) { return histoheight - Math.round(d / n * 32 * histoheight); },
    n = 1;

var area = d3.area()
    .curve(d3.curveStepBefore)
    .x(x)
    .y0(y(0))
    .y1(y);

var line = d3.line()
    .curve(d3.curveStepBefore)
    .x(x)
    .y(y);

var brush = d3_brush.brush()
    .on("start brush", brushed)
    .on("end", brushended);

var svg = d3.select("svg");

var histogram = svg.append("g")
    .attr("class", "histogram")
    //.attr("transform", "translate(" + histomargin.left + "," + histomargin.top + ")");

histogram.append("rect")
    .attr("class", "histogram-panel")
    .attr("x", -0.5)
    .attr("y", -0.5)
    .attr("width", histowidth + 1)
    .attr("height", histoheight + 1);

var histoarea = histogram.selectAll(".histogram-area")
    .data([r, g, b])
  .enter().append("path")
    .attr("class", function(d, i) { return "histogram-area histogram-" + "rgb"[i]; });

var histoline = histogram.selectAll(".histogram-line")
    .data([r, g, b])
  .enter().append("path")
    .attr("class", function(d, i) { return "histogram-line histogram-" + "rgb"[i]; })
    .attr("transform", "translate(0.5,-0.5)");

var image = new Image;
image.src = "papua-coast-web.jpg";
image.onload = loaded;

function loaded() {
  context.drawImage(this, 0, 0, width, height);

  svg.append("g")
      .attr("class", "brush")
      .call(brush)
      .call(brush.move, [[100, 350], [200, 450]]);
}

function brushed() {
  var s = d3.event.selection,
      x = s[0][0],
      y = s[0][1],
      w = s[1][0] - x,
      h = s[1][1] - y;

  for (var i = 0; i < 256; ++i) {
    r[i] = g[i] = b[i] = 0;
  }

  if (n = w * h) {
    var data = context.getImageData(x, y, w, h).data;
    for (var i = 0; i < w; ++i) {
      for (var j = 0; j < h; ++j) {
        var k = j * w + i << 2;
        ++r[data[k]];
        ++g[data[k + 1]];
        ++b[data[k + 2]];
      }
    }
    histoarea.attr("d", area);
    histoline.attr("d", line);
  } else {
    histoarea.attr("d", null);
    histoline.attr("d", null);
  }
}

function brushended() {
  if (!d3.event.selection) {
    histoarea.attr("d", null);
    histoline.attr("d", null);
  }
}

</script>