Tree generator
by jcubed111
HTML
<script src="https://cdn.jsdelivr.net/lodash/4.16.4/lodash.min.js"></script>
<canvas id='canvas' width='500' height='500'></canvas>
CSS
body{
background:#EEE;
}
canvas{
width:500px;
height:500px;
background:#FFF;
border:1px solid #CCC;
}
JavaScript
"use strict";
var ctx = document.getElementById('canvas').getContext('2d');
ctx.scale(1, -1);
ctx.translate(0, -500);
var nodes = [];
nodes = [[250, 50]];
for(var i=1; i<_.random(14, 18); i++) {
nodes.push([0, 0]);
}
var dist = 30;
function generate() {
var angle = _.random(45, 135);
var periods = [
_.random(10, 14, true),
_.random(10, 14, true),
];
var offsets = [
_.random(0, periods[0], true),
_.random(0, periods[1], true),
];
var factors = [
1,
0.5,
];
var slant = _.random(-30, 30, true);
var minAmp = 40;
var maxAmp = 130;
for(var i=1; i<nodes.length; i++) {
var prev = nodes[i-1];
var cur = nodes[i];
var components = _.map(periods, (p, j) => {
return Math.sin((i - offsets[j])/periods[j] * 2 * Math.PI) * factors[j];
});
components.push(slant / 180 * Math.PI);
var sinFac = _.sum(components);
sinFac /= _.sum(factors);
var ampFac = 1 - 2 * Math.abs(i / nodes.length - 0.5);
var amp = minAmp + ampFac * (maxAmp - minAmp)
angle = 90 + sinFac * amp;
prev.sinFac = sinFac;
prev.amp = amp;
cur[0] = 30 * Math.cos(angle / 180 * Math.PI) + prev[0];
cur[1] = 30 * Math.sin(angle / 180 * Math.PI) + prev[1];
}
}
function render() {
ctx.beginPath();
nodes.forEach(n => {
ctx.lineTo(n[0], n[1]);
});
ctx.strokeStyle = '#000';
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, 250);
ctx.lineTo(500, 250);
ctx.strokeStyle = '#ccc';
ctx.stroke();
ctx.beginPath();
nodes.forEach((n, i) => {
ctx.lineTo(i*10, 250 + n.sinFac * n.amp);
});
ctx.strokeStyle = '#f00';
ctx.stroke();
// amp
ctx.beginPath();
nodes.forEach((n, i) => {
ctx.lineTo(i*10, 250 + n.amp);
});
ctx.strokeStyle = '#f0f';
ctx.stroke();
ctx.beginPath();
nodes.forEach((n, i) => {
ctx.lineTo(i*10, 250 - n.amp);
});
ctx.strokeStyle = '#f0f';
ctx.stroke();
}
generate();
render();