1.9 揭示分形学的魔力:绘制鬼树
先说说最重要的,什么是分形学?如果你还不知道,分形学就是数学与艺术结合后的产物,并且,在生活中的任何模型中都能找到。从算法上讲,分形学是基于一个递归的方程式。本节,我们将创建一个感官能够感受到的树,绘制该树时,先绘制一个有两个树杈的树干,然后在两个树杈上分别绘制了解更多的树枝。经过12次迭代之后,我们得到的结果就是一个非常精致、看上去杂乱无章的粗枝和细枝的网状物。
按照以下步骤使用分形学绘制一颗树:
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来实现它。绘制分叉为两个树叉的树枝的最简单方法是,绘制两条相互向外弯曲的二次曲线。
假如每次迭代,我们都使用完全相同的过程,绘制的树将是完全对称的,这很无聊。为了让我们绘制的树看上去更自然,我们可以引入随机数变量,来补全每个树枝的末端。
了解更多
本节很有趣的事情是,每个树都不一样。如果你自己把代码搞上去,并不断刷新浏览器,你将会看到每棵树的形状都是独一无二的。你也可能感兴趣的是,稍微改造一下绘制树枝的算法来创作不同类型的树,或在最小的树枝上画出树叶。
在海贝, 雪花, 羽毛, 状物生命体, 水晶, 山脉, 河流, 闪电中,可以找到分形学的另外一些很棒的例子。