growing a tree

experimenting with canvas

by GertG

HTML

<p><canvas class="tree" width="800" height="600" /></p>
<button id="grow-tree">grow</button>
<input id="hue" type="range" min="0" max="359" />
<div id="swatch" style=""></div>
<div id="fps">?</div>

CSS

#swatch {
 width:100px;height:50px;   
}
#hue {
    width:700px;
}

JavaScript

(function() {

    var requestAnimationFrame = (function() {
        return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
        function(callback, element) {
            window.setTimeout(callback, 1000 / 16);
        };
    })();

    var branches = [];
    var growth_rate = 2;
    var maximum_bend = 90 / 180 * Math.PI;
    var smallest_branch = 30;
    var hue = 0;
    var fps;
    var canvas;
    var ctx;

    var avgTime = 0;
    var frameCounter = 0;
    var trackFrames = 60;

    function each(array, fn) {
        var idx = 0,
            len = array.length;

        for (; idx < len; idx++) {
            fn(array[idx]);
        }
    }

    $(function() {
        canvas = $('canvas.tree')[0];
        ctx = canvas.getContext('2d');

        $('#grow-tree').click(plant_tree);

        var swatch = $('#swatch');
        fps = $('#fps');

        $('#hue').change(function(a, b) {
            hue = a.currentTarget.value;
            swatch.css({
                'background-color': hsl(50)
            });
        });

        ctx.lineCap = 'square';

        plant_tree();

        loop();
    });

    function hsl(lightness) {
        return 'hsl(' + hue + ',70%,' + lightness + '%)';
    }

    function loop(onFrame) {

        var startDate = new Date();

        update();
        draw(ctx);

        var endDate = new Date();
        var duration = (endDate - startDate);
        avgTime += duration;

        frameCounter++;
        if (frameCounter >= trackFrames) {
            avgTime = avgTime / trackFrames;
            var avgFps = Math.floor(1000 / avgTime);
            if (avgFps > 60) avgFps = 60;

            fps.text(avgFps);
            avgTime = 0;
            frameCounter = 0;
        }

        requestAnimationFrame(loop);
    }

    function plant_tree() {
        var magnitude = 100,
            l = 50,
           ...