当前位置: 首页 > 文档资料 > HTML5 Canvas 实战 >

1.9 揭示分形学的魔力:绘制鬼树

优质
小牛编辑
124浏览
2023-12-01

先说说最重要的,什么是分形学?如果你还不知道,分形学就是数学与艺术结合后的产物,并且,在生活中的任何模型中都能找到。从算法上讲,分形学是基于一个递归的方程式。本节,我们将创建一个感官能够感受到的树,绘制该树时,先绘制一个有两个树杈的树干,然后在两个树杈上分别绘制了解更多的树枝。经过12次迭代之后,我们得到的结果就是一个非常精致、看上去杂乱无章的粗枝和细枝的网状物。

绘制鬼树
图1-13 绘制鬼树

按照以下步骤使用分形学绘制一颗树:

1. 创建一个递归函数,该函数绘制一个单一树枝,该树枝又分叉为两个树枝。然后递归调用自己,在新生成的两个树枝末端,再绘制另外两个树枝:

function drawBranches(context, startX, startY, trunkWidth, level) {
  if (level < 12)  {
    var changeX   =  100  /  (level  +  1); 
    var changeY   =  200  /  (level  +  1);
    var topRightX = startX  + Math.random()  * changeX;
    var topRightY = startY  - Math.random()  * changeY;
    var topLeftX  = startX  - Math.random()  * changeX;
    var topLeftY  = startY  - Math.random()  * changeY;
    //绘制右侧树枝
    context.beginPath();
    context.moveTo(startX  + trunkWidth  /  4, startY);
    context.quadraticCurveTo(startX + trunkWidth / 4, startY - trunkWidth, topRightX, topRightY);
    context.lineWidth  = trunkWidth; context.lineCap  = "round";
    context.stroke();
    //绘制左侧树枝
    context.beginPath();
    context.moveTo(startX  - trunkWidth  /  4, startY);
    context.quadraticCurveTo(startX - trunkWidth / 4, startY - trunkWidth, topLeftX, topLeftY);
    context.lineWidth  = trunkWidth; 
    context.lineCap  = "round";
    context.stroke();
    drawBranches(context, topRightX, topRightY, trunkWidth * 0.7, level + 1);
    drawBranches(context, topLeftX, topLeftY, trunkWidth * 0.7, level  +  1);
  }
}

2. 初始化画布上下文,并调用drawBranches()函数绘制该分形树:

window.onload  = function(){
  canvas  = document.getElementById("myCanvas");
  context = canvas.getContext("2d");
  drawBranches(context, canvas.width  /  2, canvas.height,  50,  0);
};

3. 在HTML文档的body部分嵌入canvas标签:

<canvas id="myCanvas" width="600" height="500" style="border:1px solid black;">
</canvas>

工作原理

要使用分形学创建一棵树,我们需要设计一个递归函数,该函数用来定义树的数学特征。如果花点时间研究一棵树(你这样想,它们非常漂亮),你就会注意到每个树枝都会分叉为更小的树枝。相应地,这些树枝再分叉为更小的树枝,以此类推。这意味着我们的递归函数应该绘制单一树枝,该树枝又分叉为两个树枝,然后再递归调用自己,来绘制从新绘制的两个树枝上生成的另外两个树枝。

既然我们已经打算创建我们的分形树,我们就可以使用HTML5的画布API来实现它。绘制分叉为两个树叉的树枝的最简单方法是,绘制两条相互向外弯曲的二次曲线。

假如每次迭代,我们都使用完全相同的过程,绘制的树将是完全对称的,这很无聊。为了让我们绘制的树看上去更自然,我们可以引入随机数变量,来补全每个树枝的末端。

了解更多

本节很有趣的事情是,每个树都不一样。如果你自己把代码搞上去,并不断刷新浏览器,你将会看到每棵树的形状都是独一无二的。你也可能感兴趣的是,稍微改造一下绘制树枝的算法来创作不同类型的树,或在最小的树枝上画出树叶。

在海贝, 雪花, 羽毛, 状物生命体, 水晶, 山脉, 河流, 闪电中,可以找到分形学的另外一些很棒的例子。