浏览器中实现的Sierpinski地毯
Sierpinski地毯,也称谢尔宾斯基地毯,是一种用正方形构建的典型的分形图,在介绍分形时也经常作为例子。Sierpinski地毯也是可以使用函数递归方式绘制,主要绘制函数代码为:
function drawRect(n,context,x,y,w,h){
if(n==0) return;
context.fillRect(x,y,w,h);
drawRect(n-1,context,(x+(1/3)*w),(y-(2/3)*h),w/3,h/3);
drawRect(n-1,context,(x+(1/3)*w),(y+(4/3)*h),w/3,h/3);
drawRect(n-1,context,(x-(2/3)*w),(y+(1/3)*h),w/3,h/3);
drawRect(n-1,context,(x-(2/3)*w),(y-(2/3)*h),w/3,h/3);
drawRect(n-1,context,(x-(2/3)*w),(y+(4/3)*h),w/3,h/3);
drawRect(n-1,context,(x+(4/3)*w),(y+(1/3)*h),w/3,h/3);
drawRect(n-1,context,(x+(4/3)*w),(y-(2/3)*h),w/3,h/3);
drawRect(n-1,context,(x+(4/3)*w),(y+(4/3)*h),w/3,h/3);
}
其中代码也是JavaScript,函数有6个参数,n为递归函数的递归深度,context为绘制图形使用的html5的canvas上下文,这是一种标准用法。后面四个参数为绘制正方形的左上角顶点坐标x和y,后面是正方形的宽度w和高度h。
使用JavaScript在canvas中绘制正方形使用context的fillRect(x,y,w,h)方法,四个参数x、y、w、h就是这个方法要用到的。在递归使用时,要先绘出中心的一个正方形,然后在其周边用递归调用方法再绘8个正方形,逐次进行下去。为了绘出周边的8个正方形,就要根据中心正方形的坐标计算出周围正方形的顶点坐标,宽度高度都按1/3绘制。
if(n==0) return是用来控制递归深度的,避免造成栈溢出。最初一次调用设定深度值,然后每次递归调用都减去1,直到0时退出。
为了使用上述绘制函数,前面要加上获取canvas及context的代码,为了适应不同的canvas宽度和高度,也设置了几个变量。然后把这些JavaScript代码加入一个网页的html框架中。最终代码为:
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="gb18030" />
<meta http-equiv="refresh" content="9999" />
<title>分形</title>
</head>
<body>
<canvas id="canvas" width="600" height="600"> 你使用的浏览器不支持需要的功能,请升级或更换!</canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
width=canvas.width,
height=canvas.height,
ww=canvas.width/3,
hh=canvas.height/3,
halfwidth=canvas.width/2,
halfheight=canvas.height/2;
window.onload=function() {
ctx.lineWidth=1;
ctx.fillStyle='#66aaaa';
drawRect(5,ctx,halfwidth-ww/2,halfheight-hh/2,ww,hh);
};
function drawRect(n,context,x,y,w,h){
if(n==0) return;
context.fillRect(x,y,w,h);
drawRect(n-1,context,(x+(1/3)*w),(y-(2/3)*h),w/3,h/3);
drawRect(n-1,context,(x+(1/3)*w),(y+(4/3)*h),w/3,h/3);
drawRect(n-1,context,(x-(2/3)*w),(y+(1/3)*h),w/3,h/3);
drawRect(n-1,context,(x-(2/3)*w),(y-(2/3)*h),w/3,h/3);
drawRect(n-1,context,(x-(2/3)*w),(y+(4/3)*h),w/3,h/3);
drawRect(n-1,context,(x+(4/3)*w),(y+(1/3)*h),w/3,h/3);
drawRect(n-1,context,(x+(4/3)*w),(y-(2/3)*h),w/3,h/3);
drawRect(n-1,context,(x+(4/3)*w),(y+(4/3)*h),w/3,h/3);
}
</script>
</body>
</html>
因为绘制是使用fillRect(x,y,w,h)方法,其中需要用到填充正方形空间的颜色,这里使用ctx.fillStyle='#66aaaa'来设置,可以通过更改后面的6个16进制数值来改变颜色。
把上述代码复制到一种不带格式的编辑器中,比如我常使用的notepad++,当然也可以使用vscode等其他程序编辑软件,存为.html文件,比如存到桌面上,然后就可以直接点击这个文件,让其在默认浏览器中运行,然后就能显示出图形。
感兴趣的可以试试效果。