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:
Bacana, não?! Outro exemplo:
Mais um …
Último:
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;
Publicado em 28/10/2011
0