(click to reload)
A fork of Mike Bostock's branched random walk. The code has been refactored to allow a pen up/down operation, model was paramaterized further, and three variants with slightly different model settings are shown.
xxxxxxxxxx
<meta charset="utf-8">
<canvas width="960" height="500"></canvas>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script language="javascript" type="text/javascript" src="focusedRandom.js"></script>
<script>
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
width = canvas.width,
height = canvas.height,
tail_y = [0.2 * canvas.height, 0.5 * canvas.height, 0.8 * canvas.height],
randomY = d3.randomNormal(0,1.5),
randomPenToUp = d3.randomUniform(-15, 1),
randomPenToDown = d3.randomUniform(-5, 1);
render();
canvas.onclick = render;
function render() {
context.clearRect(0, 0, width, height);
render_tail(0);
render_tail(1);
render_tail(2);
}
function render_tail(which_tail) {
var length = Math.floor(focusedRandom(80, 1200, 2, 900));
var tail_length = Math.floor(focusedRandom(60, 400, 3, 200));
var tail_every = Math.floor(focusedRandom(1, 30, 4, 4));
var color = d3.scaleSequential(d3.interpolateRainbow).domain([0, length]);
var x_bias = 600 / length;
var local_randomX = d3.randomNormal(x_bias,2);
var x0 = width / 20,
y0 = tail_y[which_tail],
pen_up0 = false,
tail_chunk = Math.floor(tail_length / 20),
mainWalk = randomWalk([[x0, y0, pen_up0, null]], length, local_randomX);
context.lineJoin = "round";
context.lineCap = "round";
context.lineWidth = 1.5;
context.strokeStyle = "black";
renderWalk(mainWalk);
context.globalCompositeOperation = "multiply";
context.lineWidth = 1;
for (var i = tail_every; i < mainWalk.length; i += tail_every) {
var branchHistory = mainWalk.slice(0, i+1)
for (var j = 0; j < 1; ++j) {
context.strokeStyle = color(i);
branchCopy = branchHistory.slice();
for (var k = 0, m = 20; k < m; ++k) {
context.globalAlpha = (m - k - 1) / m;
var pieceWalk = randomWalk(branchCopy, tail_chunk, local_randomX),
pieceEnd = pieceWalk[pieceWalk.length - 1];
renderWalk(pieceWalk);
branchCopy.push(pieceEnd)
}
context.globalAlpha = 1;
}
}
}
function renderWalk(walk) {
var i, n = walk.length;
context.beginPath();
context.moveTo(walk[0][0], walk[0][1]);
for (i = 0; i < n; ++i) {
// check for pen_up
if(walk[i][2]) {
context.moveTo(walk[i][0], walk[i][1]);
}
else {
context.lineTo(walk[i][0], walk[i][1]);
}
}
context.stroke();
}
function randomWalk(history, n, local_randomX) {
var points, i, x, y, pen_up, randomPenFn;
points = new Array(n);
points[0] = history[history.length - 1];
[x, y, pen_up] = points[0];
for (i = 1; i < n; ++i) {
randomPenFn = pen_up ? randomPenToDown : randomPenToUp;
points[i] = [
x += local_randomX(),
y += randomY(),
pen_up ^= (randomPenFn() > 0)
];
}
return points;
}
</script>
https://d3js.org/d3.v4.min.js