开篇
本文旨在使用cavas实现一棵随机“树”。功能并不复杂,单纯是考验对cavas的应用。
效果展示
使用cavas生成随机“树”
思路分析
生成树的关键点只有以下几个:
- 生成树干
- 在树干的基础上生成树枝(此处应该使用递归的方式生成树干,但要注意对退出条件的判定)
- 要逐步生成树枝,需要使用animate,并控制绘制命令的执行
代码实现
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<canvas></canvas>
<script src="./script.js"></script>
</body>
</html>
CSS文件
*,
html {
margin: 0;
padding: 0;
}
body {
max-height: 100%;
width: 100%;
}
canvas {
height: 70vh;
width: 100%;
background-color: lightgoldenrodyellow;
}
js文件
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth * devicePixelRatio;
canvas.height = window.innerHeight * devicePixelRatio;
// 跳转坐标原点至页面底部中间的位置
ctx.translate(canvas.width / 2, canvas.height);
ctx.scale(1, -1);
// 存储绘制命令而不是立即执行它们
let drawCommands = [];
function drawBranch(v0, length, thick, dir) {
if (thick < 10 && Math.random() < 0.3) {
return;
}
// 将函数和参数添加到命令列表中而不是立即执行
drawCommands.push({ fn: 'line', v0: v0, length: length, thick: thick, dir: dir });
if (thick < 2) {
// 生成花朵的绘制命令
drawCommands.push({ fn: 'flower', v0: v0 });
return;
}
const v1 = [
v0[0] + length * Math.cos((dir * Math.PI) / 180),
v0[1] + length * Math.sin((dir * Math.PI) / 180)
];
// 递归调用绘制树枝的命令
drawBranch(v1, length * 0.8, thick * 0.8, dir + Math.random() * 30);
drawBranch(v1, length * 0.8, thick * 0.8, dir - Math.random() * 30);
}
// 执行绘制命令
function executeCommand(command) {
if (command.fn === 'line') {
ctx.beginPath();
ctx.moveTo(...command.v0);
const v1 = [
command.v0[0] + command.length * Math.cos((command.dir * Math.PI) / 180),
command.v0[1] + command.length * Math.sin((command.dir * Math.PI) / 180)
];
ctx.lineTo(...v1);
ctx.lineWidth = command.thick;
ctx.strokeStyle = '#333';
ctx.lineCap = 'round';
ctx.stroke();
} else if (command.fn === 'flower') {
ctx.beginPath();
ctx.arc(...command.v0, 10, 0, 2 * Math.PI);
ctx.fillStyle = 'pink';
ctx.fill();
}
}
// 动画绘制
function animate() {
// 如果有待执行的命令,则执行一个并请求下一帧
if (drawCommands.length > 0) {
executeCommand(drawCommands.shift());
requestAnimationFrame(animate);
}
}
// 开始绘制树干,这将填充绘制命令数组
drawBranch([0, 0], 200, 30, 90);
// 开始动画
animate();
注
上面便是使用cavas实现随机树的全部逻辑,希望对您有所帮助。
感谢阅读w