这个效果是用递归的方式,不断画出线条组成一棵简单的小树形象。
1 、规定 一个树枝上最大的子树枝数(maxBranch=3)三根【这个值可以随便设置】,利用 js 中的随机数生成1-3的数 subBranches = Math.random()*(maxBranch-1)+1 ,
这样子树枝数就是随机的。每次递归循环画出 subBranches 根子树干。
2、 每个子树枝都有个角度angle,angle是等于父树枝角度加上子树枝偏离父树枝角度。设子树枝偏离父树枝最大值为45度【计算时都以弧度值计算】: maxAngle=Math.PI/4,
每次递归循环时偏离值都是从0到maxAngle的随机数,并且为了使树看起来更符合实际,这个偏离角度可为正和负,为了得到树枝角度:
首先利用 js 随机函数 Math.random()*maxAngle*2 生成 0 到 2*maxAngle 弧度的随机数,然后减去 maxAngle,这样就得到了 -maxAngle 到 maxAngle 的随机弧度值。
newAngle = angle+(Math.random()*maxAngle*2-maxAngle);
3 、branchwidth 树枝的宽度是递减的,每次递归循环branchwidth乘上一个小数按比例减小, branchwidth*=0.7 。
4、通过 depth 可以控制递归次数,depth越大树越茂盛,树枝节数越多。depth是递减的,当设当depth小于等于2的时候,就代表是叶子,及把划线颜色设置为随机的绿色或者其他颜色。
最终效果及源码如下:
html 代码效果预览
<!doctype html> <html> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> <title>canvas画图实例</title> <meta http-equiv="X-UA-Compatible" content="IE=7" /> <meta name="keywords" content="" /> <meta name="description" content="" /> <style> body{} #canvas{ background: #ccc} #tree{ background: #eeffee} </style> </head> <body> <canvas id="tree" width="800px" height="500px">您的浏览器不支持 canvas 标签</canvas> </div> <script> window.onload=function(){ var tree= document.getElementById('tree'); var ctx=tree.getContext('2d'); drawTree(ctx,tree.width/2,tree.height-50,60,-Math.PI/2,11,12); drawTree(ctx,tree.width/2-60,tree.height,20,-Math.PI/2,5,3); drawTree(ctx,tree.width/2+60,tree.height-20,20,-Math.PI/2,6,3); drawTree(ctx,70,150,20,-Math.PI/2,8,3); } /** * [drawTree description] * @param ctx [画布] * @param startX [树的起始 x 坐标] * @param startY [树的起始 y 坐标] * @param length [树干长度] * @param angle [树干方向,以坐标系x轴正方向为0度] * @param depth [树干的节数] * @param branchwidth [树干宽度] */ function drawTree(ctx,startX,startY,length,angle,depth,branchwidth){ var rand = Math.random, newLength,newAngle,newDepth,maxBranch=3,endX,endY,maxAngle=Math.PI/4, /* 树枝数量 */ subBranches; ctx.beginPath(); ctx.moveTo(startX,startY); endX=startX+length*Math.cos(angle); endY=startY+length*Math.sin(angle); ctx.lineCap='round'; ctx.lineWidth=branchwidth; ctx.lineTo(endX,endY); if(depth<=2){ //ctx.strokeStyle='rgb(237,'+parseInt(((rand()*64)+100))+',65)'; ctx.strokeStyle='rgb(0,'+parseInt(((rand()*64)+128))+',0)'; /*颜色用了随机数,这样使颜色看起来有深有浅,比较符合实际 */ }else{ ctx.strokeStyle='rgb('+parseInt(((rand()*64)+64))+',50,25)'; /*颜色用了随机数,这样使颜色看起来有深有浅,比较符合实际 */ } ctx.stroke(); newDepth=depth-1; if(!newDepth){ return; } subBranches=rand()*(maxBranch-1)+1; branchwidth*=0.7; setTimeout(function(){ for(var i=0;i<subBranches;i++){ newAngle=angle+rand()*maxAngle*2-maxAngle; newLength=length*(0.7+rand()*0.3); drawTree(ctx,endX,endY,newLength,newAngle,newDepth,branchwidth); } },100); } </script> </body> </html>