<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML5 勾股树植物生长动画</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #000;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
font-family: 'Arial', sans-serif;
}
.container {
position: relative;
width: 100%;
height: 100%;
}
canvas {
display: block;
background: #000;
}
.controls {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 15px;
z-index: 10;
}
button {
padding: 10px 20px;
background: rgba(0, 128, 0, 0.7);
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
transition: all 0.3s ease;
backdrop-filter: blur(5px);
}
button:hover {
background: rgba(0, 128, 0, 0.9);
transform: translateY(-2px);
}
button:active {
transform: translateY(1px);
}
.title {
position: absolute;
top: 30px;
left: 0;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.8);
font-size: 2.5rem;
text-shadow: 0 0 10px rgba(0, 255, 0, 0.5);
z-index: 10;
}
.footer {
position: absolute;
bottom: 10px;
left: 0;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.5);
font-size: 12px;
z-index: 10;
}
.footer a {
color: rgba(0, 255, 0, 0.7);
text-decoration: none;
transition: all 0.3s ease;
}
.footer a:hover {
color: #0f0;
text-decoration: underline;
}
@media (max-width: 768px) {
.title {
font-size: 1.8rem;
}
.controls {
flex-direction: column;
align-items: center;
}
}
</style>
</head>
<body>
<div class="container">
<h1 class="title">勾股树植物生长动画</h1>
<canvas id="treeCanvas"></canvas>
<div class="controls">
<button id="growBtn">开始生长</button>
<button id="resetBtn">重置</button>
<button id="changeColorBtn">改变颜色</button>
</div>
<div class="footer">
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const canvas = document.getElementById('treeCanvas');
const ctx = canvas.getContext('2d');
const growBtn = document.getElementById('growBtn');
const resetBtn = document.getElementById('resetBtn');
const changeColorBtn = document.getElementById('changeColorBtn');
// 设置画布大小
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
// 动画参数
let animationId = null;
let growthProgress = 0;
let maxDepth = 10;
let branchColor = '#00aa00';
let leafColor = '#00ff00';
let angle = Math.PI / 4; // 45度
let branchShrinkFactor = 0.7;
let isGrowing = false;
// 颜色方案
const colorSchemes = [
{ branch: '#00aa00', leaf: '#00ff00' }, // 绿色
{ branch: '#8B4513', leaf: '#228B22' }, // 棕色/绿色
{ branch: '#4B0082', leaf: '#9370DB' }, // 紫色
{ branch: '#B22222', leaf: '#FF6347' }, // 红色/橙色
{ branch: '#1E90FF', leaf: '#87CEFA' } // 蓝色
];
let currentColorScheme = 0;
// 绘制勾股树
function drawPythagorasTree(startX, startY, length, angle, depth, progress) {
if (depth > maxDepth * progress) return;
const endX = startX - length * Math.sin(angle);
const endY = startY - length * Math.cos(angle);
// 设置线条宽度和颜色
const lineWidth = Math.max(1, depth / 2);
ctx.lineWidth = lineWidth;
// 根据深度决定颜色
const color = depth < maxDepth * 0.3 ? leafColor : branchColor;
ctx.strokeStyle = color;
ctx.fillStyle = color;
// 绘制树枝
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.lineTo(endX, endY);
ctx.stroke();
// 如果是叶子,绘制一个小圆
if (depth > maxDepth * 0.8) {
ctx.beginPath();
ctx.arc(endX, endY, lineWidth * 1.5, 0, Math.PI * 2);
ctx.fill();
}
// 计算新长度
const newLength = length * branchShrinkFactor;
// 递归绘制左右分支
drawPythagorasTree(
endX,
endY,
newLength,
angle + Math.PI / 4 * (0.5 + Math.random() * 0.5),
depth + 1,
progress
);
drawPythagorasTree(
endX,
endY,
newLength,
angle - Math.PI / 4 * (0.5 + Math.random() * 0.5),
depth + 1,
progress
);
}
// 动画循环
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 计算生长进度
if (isGrowing && growthProgress < 1) {
growthProgress += 0.005;
if (growthProgress > 1) growthProgress = 1;
}
// 绘制树
drawPythagorasTree(
canvas.width / 2,
canvas.height - 50,
Math.min(canvas.width, canvas.height) / 5,
0,
0,
growthProgress
);
animationId = requestAnimationFrame(animate);
}
// 开始动画
animate();
// 事件监听
growBtn.addEventListener('click', function() {
isGrowing = !isGrowing;
growBtn.textContent = isGrowing ? '暂停生长' : '继续生长';
});
resetBtn.addEventListener('click', function() {
growthProgress = 0;
isGrowing = false;
growBtn.textContent = '开始生长';
});
changeColorBtn.addEventListener('click', function() {
currentColorScheme = (currentColorScheme + 1) % colorSchemes.length;
branchColor = colorSchemes[currentColorScheme].branch;
leafColor = colorSchemes[currentColorScheme].leaf;
});
// 鼠标交互 - 改变角度
canvas.addEventListener('mousemove', function(e) {
if (!isGrowing) {
// 根据鼠标X位置计算角度 (0到PI/2之间)
angle = (e.clientX / canvas.width) * Math.PI / 2;
}
});
// 防止内存泄漏
window.addEventListener('beforeunload', function() {
cancelAnimationFrame(animationId);
});
});
</script>
</body>
</html>