'use strict'; var canvas = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); canvas.setAttribute('width', '400'); canvas.setAttribute('height', '300'); document.body.appendChild(canvas); var appendToSVG = function(limb) { var e = document.createElementNS('http://www.w3.org/2000/svg', 'line'); var x2 = limb.x + limb.length * Math.cos(limb.angle); var y2 = limb.y + limb.length * Math.sin(limb.angle); e.setAttribute('x1', limb.x); e.setAttribute('y1', limb.y); e.setAttribute('x2', x2); e.setAttribute('y2', y2); e.style.stroke = limb.color; e.style.strokeWidth = limb.width; canvas.appendChild(e); e = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); e.setAttribute('cx', x2); e.setAttribute('cy', y2); e.setAttribute('r', randBetween(2, 5)); e.style.fill = 'darkgreen'; e.style.fillOpacity = 0.1; canvas.appendChild(e); }; var base = { x: 150, y: 200, length: 50, angle: -Math.PI / 2, width: 1, color: 'brown', limbs: [], generation: 0 }; var maxGeneration = 6; var maxLimbs = 3; var randBetween = function(min, max) { return Math.random() * (max - min) + min; }; var createLimb = function() { return { x: this.x + this.length * Math.cos(this.angle), y: this.y + this.length * Math.sin(this.angle), length: randBetween(1, this.length), angle: -randBetween(0, Math.PI), width: this.width / 2, color: this.color, limbs: [], generation: this.generation + 1 }; }; var createLimbs = function(limb) { if (limb.generation < maxGeneration) { var n = Math.round(Math.random() * maxLimbs) + 1; for (var i = 0; i < n; i++) limb.limbs.push(createLimb.call(limb)); limb.limbs.forEach(createLimbs); } }; var iterateLimbs = function(root, cb) { cb(root); root.limbs.forEach(function(limb) { cb(limb); iterateLimbs(limb, cb); }); }; createLimbs(base); iterateLimbs(base, appendToSVG);