Amazing Trees (html5)

Publicado em 28/10/2011

0


Olá pessoal, tudo certo?!

No post de hoje, mostro uma variação do fractal “tree” que apresentei há alguns dias. Basicamente, adicionei alguma “aleatoriedade” e cor. Veja alguns resultados:

image

Bacana, não?! Outro exemplo:

 

image

Mais um …

image

Último:

image

Agora, vamos ver como é o código.

Aliás, o código-fonte está em https://gist.github.com/1323773 e há um live demo em http://users.cjb.net/livedemoelemarjr/amazingtrees.htm

CanvasAdapter

Mais uma vez, construo uma classe para “interfacear” com o elemento Canvas. Observe:


              
function CanvasAdapter(canvas, context) {
    this.canvas = canvas;
    this.context = context;

    this.canvasWidth = canvas.width;
    this.canvasHeight = canvas.height;

    this.clear = function () {
        this.context.clearRect(0, 0,
            this.canvasWidth,
            this.canvasHeight
            );
    };

    this.drawLine = function (x1, y1, x2, y2, pen) {
        with (this.context) {
            beginPath();
            moveTo(x1, this.canvasHeight - y1);
            lineTo(x2, this.canvasHeight - y2);
            lineWidth = pen;
            lineCap = "round";
            stroke();
        }
    };
}

var canvas = $('#target');
var context = canvas.get(0).getContext('2d');
var ca = new CanvasAdapter(canvas, context);

            

Como pode ver, crio uma camada para as funções da api do elemento canvas. Assim, penso eu, acabo “isolando” a complexidade acidental.

Perceba, no código acima, que crio imediatamente uma instância dessa classe. Esse objeto é atualizado, constantemente, no “handler” do evento resize (que venho usando há algum tempo nos meus exemplos). Observe:


              
function resizeCanvas() {
    canvas.attr("width", $(window).get(0).innerWidth);
    canvas.attr("height", $(window).get(0).innerHeight);
    ca.canvasWidth = canvas.width();
    ca.canvasHeight = canvas.height();
    ca.clear();
    drawTree(12, ca.canvasWidth / 2, 10, ca.canvasHeight / 8, Math.PI / 2, 12);
};
$(window).resize(resizeCanvas);
resizeCanvas();

canvas.click(function () {
    ca.clear();
    drawTree(12, ca.canvasWidth / 2, 10, ca.canvasHeight / 8, Math.PI / 2, 12);
});

            

São apenas dois eventos mapeados. Um para o resize, outro para o clique. Em ambos, chamo a rotina que efetiva o desenho.

Vamos explicar o método drawTree?!

O método drawTree

Como desenho a árvore?! Simples. Observe:


              
var drawTree = function (depth, x, y, length, theta, branchWidth) {

    if (depth < 0) return;

    var rand = Math.random;
    var maxAngle = Math.PI / 2;
    var x2 = x + length * Math.cos(theta);
    var y2 = y + length * Math.sin(theta);

    ca.context.strokeStyle = (depth <= 2) ?
        'rgb(0,' + parseInt(rand() * 64 + 128) + ',0)' :
        'rgb(' + parseInt(rand() * 64 + 64) + ',50,25)';

    ca.drawLine(x, y, x2, y2, branchWidth);

    var subBranches = rand() * 2 + 1;
    for (var i = 0; i < subBranches; i++) {
        drawTree(
            depth - 1,
            x2, y2,
            length * (0.7 + rand() * 0.3),
            theta + rand() * maxAngle - 0.5 * maxAngle,
            branchWidth * 0.7
            );
    }
};

            

Como você pode perceber, o método é muito parecido com aquele que mostrei no post explicando o fractal tree. As diferenças:

  • Utilizo tons de verde nas pontas (final da recursão), e marrom nos demais níveis;
  • Os galhos iniciais são mais “espessos”;
  • Em cada nível, o número de galhos varia entre 1 e 3;
  • o redução do comprimento dos “galhos”, em cada nível,  está entre 0% a 30%;
  • o ângulo de “abertura” dos galhos filhos é variável (nunca maior que 90 graus).

Bacana.

Era isso;

Smiley piscando

Publicado em: Post