Skip to content

Instantly share code, notes, and snippets.

@curran
Last active April 12, 2017 10:24
Show Gist options
  • Save curran/5a916bd8381260412978c748ed685106 to your computer and use it in GitHub Desktop.
Save curran/5a916bd8381260412978c748ed685106 to your computer and use it in GitHub Desktop.
Robot Painter
An experiment related to https://github.com/d3/d3-array/issues/56
This shows how repeated iterations of a simple moving average acts as a [Gaussian Filter](https://en.wikipedia.org/wiki/Gaussian_filter).
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
* {
margin:0;
position:fixed;
top:0;
right:0;
bottom:0;
left:0;
}
</style>
</head>
<body>
<canvas id="rainbow" width="960" height="500"></canvas>
<canvas id="foreground" width="960" height="500"></canvas>
<script>
const numRandomPoints = 300;
const numHistogramBins = 500;
const width = 960;
const height = 500;
const randomPoints = d3.range(numRandomPoints).map(d3.randomNormal());
const histogram = d3.histogram()
.domain([-3, 3])
.thresholds(numHistogramBins);
let data = histogram(randomPoints)
.map(d => Object.assign({}, d, { density: d.length}));
const yValue = d => d.density;
const xValue = d => (d.x0 + d.x1) / 2;
const xScale = d3.scaleLinear()
.domain(d3.extent(data, xValue))
.range([0, width]);
const yScale = d3.scaleLinear()
.domain([0, 2])
.range([height, 0]);
const rainbow = d3.select("#rainbow").node().getContext("2d");
const foreground = d3.select("#foreground").node().getContext("2d");
const area = d3.area()
.x(d => xScale(xValue(d)))
.y0(yScale(0))
.y1(d => yScale(yValue(d)));
function renderHistogram(elapsed){
const t = elapsed / 2 + 175; // Start at blue
rainbow.beginPath();
area.context(rainbow)(data);
rainbow.strokeStyle = d3.hsl(t, 1, 0.5, (5000 - elapsed)/5000);
rainbow.stroke();
}
function blur(data){
return data.map((d, i) => {
const previous = (i === 0) ? i : i - 1;
const sum = data[previous].density + d.density;
d.density = sum / 2;
return d;
});
}
d3.timer((elapsed) => {
data = blur(data);
renderHistogram(elapsed);
});
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment