Skip to content

Instantly share code, notes, and snippets.

@d2fn
Last active March 11, 2021 12:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save d2fn/0d3789278f3d9816e0fd to your computer and use it in GitHub Desktop.
Save d2fn/0d3789278f3d9816e0fd to your computer and use it in GitHub Desktop.
Perlin Curves I

Curves drawn by randomly placing actors on the canvas, and walking them in a direction determined by the perlin noise function at their location. The continuity of the underlying noise function causes paths to converge together.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
background: rgb(255, 255, 255);
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="/d2fn/raw/8777d620caef32959713/perlin.js"></script>
<script>
var width = 960,
height = 500,
noiseScale = 0.003,
actorStepLength = 1,
numActors = 10000,
step = 0,
steps = 150;
var canvas = d3.select("body")
.append("canvas")
.attr({width: width, height: height});
var context = canvas.node().getContext("2d");
context.fillStyle = "rgb(0, 0, 0)";
context.fillRect(-1, -1, width, height);
var actors = [];
for(var i = 0; i < numActors; i++) {
actors.push(actor(width, height, noiseScale, actorStepLength));
}
var opacity = easeInOut(steps);
d3.timer(function() {
if(++step > steps) {
console.log("done with animation");
return true;
}
context.lineWidth = 1;
context.globalCompositeOperation = 'lighter';
context.beginPath();
for(var i in actors) {
var a = actors[i];
var ln = a.step();
var alpha = 0.6*opacity.get();
context.strokeStyle = "rgba(49, 130, 189, " + alpha + ")";
context.moveTo(ln.x1, ln.y1);
context.lineTo(ln.x2, ln.y2);
}
context.stroke();
opacity.step();
});
function actor(width, height, noiseScale, stepLength) {
var x = Math.random() * width,
y = Math.random() * height;
var noise = perlin.noise(noiseScale);
return {
// get the last point and the next point
step: function() {
var t = noise(x, y) * Math.PI * 5;
var x1 = x,
y1 = y;
x = x + stepLength * Math.cos(t);
y = y + stepLength * Math.sin(t);
return {
x1: x1,
y1: y1,
x2: x,
y2: y
}
}
}
}
function easeInOut(steps) {
var n = 0;
var val = 0;
return {
step:
function() {
val = 0.5*(1-Math.cos(2 * Math.PI * (n++) / steps));
},
get:
function() {
return val;
}
};
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment