用html5开发随机生成的大树,你应该没想到40+行代码就可以搞定了吧~接下来就跟大家说说这棵大树是如何在html5开发中实现的。

  同样必须要有html容器。新建Index.html,代码如下:

  <、html>

  1 <、head>

  2 <、meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

  3 <、title>canvas tree

  4 <、/head>

  5 <、body>

  6 <、script type="text/javascript" src="tree.js">

  7 <、/body>

  8 <、/html>

  接下来咱们开始tree.js:

  、var canvas = document.createElement("canvas");

  9 var ctx = canvas.getContext("2d");

  10 canvas.width = 640;

  11 canvas.height = 480;

  12 document.body.appendChild(canvas);

  代码很好理解,创建一个canvas画布,然后选择为2d画布,设置长宽,最后将这个画布添加到body标签下。

  这个脚本最重要的函数在下面,大树就是递归调用这个函数实现的,调用一次画一条线段:

  var drawTree = function (ctx, startX, startY, length, angle, depth, branchWidth){

  13 var rand = Math.random,

  14 newLength, newAngle, newDepth, maxBranch = 3,

  15 endX, endY, maxAngle = 2 * Math.PI / 4,

  16 subBraches;

  17 ctx.beginPath();

  18 ctx.moveTo(startX, startY);

  19 endX = startX + length * Math.cos(angle);

  20 endY = startY + length * Math.sin(angle);

  21 ctx.lineCap = 'round';

  22 ctx.lineWidth = branchWidth;

  23 ctx.lineTo(endX, endY);

  24 if (depth <= 2){

  25 ctx.strokeStyle = 'rgb(0,' + (((rand() * 64) + 128) >> 0) + ',0)';

  26 } else {

  27 ctx.strokeStyle = 'rgb(' + (((rand() * 64) + 64) >> 0) + ',50,25)';

  28 }

  29 ctx.stroke();

  30 newDepth = depth - 1;

  31 if (!newDepth)

  32 return;

  33 subBranches = (rand() * (maxBranch - 1)) + 1;

  34 branchWidth *= 0.7;

  35 for (var i = 0; i < subBranches; i++){

  36 newAngle = angle + rand() * maxAngle - maxAngle * 0.5;

  37 newLength = length * (0.7 + rand() * 0.3);

  38 drawTree(ctx, endX, endY, newLength, newAngle, newDepth, branchWidth);

  39 }

  40 }

  接下来一点点解释:

  首先,解释下各个变量的含义。ctx就是前面我们的2d画布;startX是线段开始的横坐标,同理startY是纵坐标;length是线段长度;angle是角度;depth是深度,叶子深度为1,树干为12(可自己设定);branchWidth就线段的粗细。有了这些信息,其实就描述了一个线段,通过这些信息我们才能画一个线段。

  接下来又很可耻地一大段定义:

  var rand = Math.random,

  41 newLength, newAngle, newDepth, maxBranch = 3,

  42 endX, endY, maxAngle = 2 * Math.PI / 4,

  43 subBraches;

  rand其实就是随机一个0~1之间的实数,顾名思义,接下来这些new的就是下一节线段的各种参数。maxBranch就是最多有3个分叉,最大的角度 PI/2 即为,下一级调整角度在90%范围内。subBranches就是分叉的个数。

  好了,重要可以画了:

  ctx.beginPath();

  44 ctx.moveTo(startX, startY);

  45 endX = startX + length * Math.cos(angle);

  46 endY = startY + length * Math.sin(angle);

  47 ctx.lineCap = 'round';

  48 ctx.lineWidth = branchWidth;

  49 ctx.lineTo(endX, endY);

  beginPath()表示告诉浏览器“我要开始画了!”,把之前的记录放弃了,这点有点像ps。moveTo()把光标移动到(startX, startY),再计算终点坐标,endX,endY,有点像高中学的参数方程。然后告诉浏览器,lineCap要round,线段的两头要是圆形的。有多粗呢?等于branchWidth。线段一直画到(endX, endY)。

  if (depth <= 2){

  50 ctx.strokeStyle = 'rgb(0,' + (((rand() * 64) + 128) >> 0) + ',0)';

  51 } else {

  52 ctx.strokeStyle = 'rgb(' + (((rand() * 64) + 64) >> 0) + ',50,25)';

  53 }

  如果是已经画到了最后两级,即为叶子,那么就rgb就为(0, 128~192, 0)(rgb代表颜色,分别为红绿蓝,red green blue)。还没的话,就在(64~128, 50 ,25)中取。大家可能发现了,rgb必须为整数,但是rand()只能rand实数。大家其实也注意到了有个” >> 0″,js当中表示位运算,整体向右移动n位,0就是移动0位。其实它的作用和Math.floor()一样,但是速度更快。

  动手画!

  ctx.stroke();

  这个线段就画好了,是时候准备下它的分叉的时候了。

  newDepth = depth - 1;

  54 if (!newDepth)

  55 return;

  如果这个线段是最后一级,就没有分叉了,也是一个递归的终止条件。

  subBranches = (rand() * (maxBranch - 1)) + 1;

  56 branchWidth *= 0.7;

  57 for (var i = 0; i < subBranches; i++){

  58 newAngle = angle + rand() * maxAngle - maxAngle * 0.5;

  59 newLength = length * (0.7 + rand() * 0.3);

  60 drawTree(ctx, endX, endY, newLength, newAngle, newDepth, branchWidth);

  61 }

  分叉数是1~3中的一个数。然后有多少个分叉,就画几条线段,newAngle为原角度调整90度之内,新长度为原长度的0.7~1.0之间。

  最后画出主干,这棵树就可以开始画了。

  drawTree(ctx, 320, 470, 60, -Math.PI / 2, 12, 12);

  大家可能注意到角度为负,不符合传统观念。但你要知道,画布的纵坐标和传统的坐标轴正好是相反的。

好了,html5开发随机生成的大树代码就这样完成了,怎么样,一点都难吧!如果你觉得这些关于html5开发的知识还没学够,你可以查询天地会多作一些了解http://bbs.9tech.cn/html5/

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐