Playing around with Harmonograph mechanics.
Last active
February 2, 2017 17:28
-
-
Save veltman/72108247a8f8304ce0ccd7a50f49a9ca to your computer and use it in GitHub Desktop.
Harmonographics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<body> | |
<canvas width="960" height="500"></canvas> | |
<script src="//d3js.org/d3.v4.min.js"></script> | |
<script> | |
var canvas = document.querySelector("canvas"), | |
context = canvas.getContext("2d"), | |
width = canvas.width, | |
height = canvas.height, | |
step = 0.015; | |
context.translate(width / 2, height / 2); | |
context.lineWidth = 0.5; | |
context.strokeStyle = "#f13f94"; | |
var scales = { | |
phase: d3.scaleLinear().range([0, Math.PI]), | |
damping: d3.scaleLinear().range([0.01, 0.05]), | |
frequency: d3.scaleLinear().range([2, 6]) | |
}; | |
var keys = d3.keys(scales); | |
var x = new Pendulum(), | |
y = new Pendulum(), | |
xy = new Pendulum(); | |
x.amplitude = y.amplitude = 150; | |
xy.amplitude = 100; | |
tween(); | |
function tween() { | |
d3.transition() | |
.duration(6000) | |
.tween("tween", function(){ | |
var p = choose([x, y, xy]), | |
scale = keys.shift(), | |
invert = p[scale] === scales[scale](1); | |
keys.push(scale); | |
return function(t){ | |
p[scale] = scales[scale](invert ? 1 - t : t); | |
draw(); | |
}; | |
}) | |
.on("end", tween); | |
} | |
function draw(){ | |
var t = 0; | |
context.clearRect(-width / 2, -height / 2, width, height); | |
context.beginPath(); | |
x.stopped = y.stopped = xy.stopped = false; | |
while (!x.stopped || !y.stopped || !xy.stopped) { | |
context[t ? "lineTo" : "moveTo"](x.pos(t) + xy.x(t), y.pos(t) + xy.pos(t)); | |
t += step; | |
} | |
context.stroke(); | |
} | |
function Pendulum() { | |
for (var key in scales) { | |
this[key] = scales[key](Math.random() < 0.5 ? 0 : 1); | |
} | |
} | |
Pendulum.prototype.pos = function(t){ | |
return this.amplitude * Math.sin(t * this.frequency + Math.PI * this.phase) * this.damp(t); | |
}; | |
Pendulum.prototype.damp = function(t){ | |
var factor = Math.exp(-this.damping * t); | |
if (factor < 0.1) { | |
this.stopped = true; | |
} | |
return factor; | |
}; | |
Pendulum.prototype.x = function(t){ | |
return this.amplitude * Math.cos(t * this.frequency) * this.damp(t); | |
}; | |
function choose(arr){ | |
return arr[Math.floor(Math.random() * arr.length)]; | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment