← back to Model Arena
data/artifacts/10c3c876aa67/qwen25-7b.html
128 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Recursive Fractal Tree</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #2b343c;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let treeDepth = 7;
let branches = [];
class Branch {
constructor(x, y, length, angle, depth) {
this.x = x;
this.y = y;
this.length = length;
this.angle = angle;
this.depth = depth;
}
draw() {
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.x + Math.cos(this.angle) * this.length, this.y - Math.sin(this.angle) * this.length);
ctx.stroke();
}
grow() {
const endX = this.x + Math.cos(this.angle) * this.length;
const endY = this.y - Math.sin(this.angle) * this.length;
if (this.depth > 0) {
branches.push(new Branch(endX, endY, this.length * 0.75, this.angle - Math.PI / 8 + Math.random() * Math.PI / 4, this.depth - 1));
branches.push(new Branch(endX, endY, this.length * 0.75, this.angle + Math.PI / 8 + Math.random() * Math.PI / 4, this.depth - 1));
ctx.strokeStyle = `hsl(${Math.floor(255 * (this.depth / treeDepth))}, 100%, ${100 - this.depth * 2}%)`;
}
}
sway() {
const angleVariation = Math.random() * Math.PI / 4 - Math.PI / 8;
ctx.save();
ctx.translate(this.x + Math.cos(this.angle) * this.length, this.y - Math.sin(this.angle) * this.length);
ctx.rotate(angleVariation);
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(0, -this.length);
ctx.stroke();
ctx.restore();
}
}
function drawTree(x, y, length, angle, depth) {
branches.push(new Branch(x, y, length, angle, depth));
if (depth > 0) {
const endX = x + Math.cos(angle) * length;
const endY = y - Math.sin(angle) * length;
ctx.strokeStyle = `hsl(${Math.floor(255 * (depth / treeDepth))}, 100%, ${100 - depth * 2}%)`;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(endX, endY);
ctx.stroke();
drawTree(endX, endY, length * 0.75, angle - Math.PI / 8 + Math.random() * Math.PI / 4, depth - 1);
drawTree(endX, endY, length * 0.75, angle + Math.PI / 8 + Math.random() * Math.PI / 4, depth - 1);
}
}
function update() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
branches.forEach(b => b.sway());
drawTree(canvas.width / 2, canvas.height, 50, 0, treeDepth);
const leafParticles = [];
for (let i = 0; i < Math.random() * 10 + 1; i++) {
const x = Math.random() * canvas.width;
const y = canvas.height + 200;
const size = 5;
const speed = 3;
leafParticles.push({x, y, size, speed});
}
ctx.beginPath();
leafParticles.forEach(leaf => {
ctx.moveTo(leaf.x, leaf.y);
ctx.arc(leaf.x, leaf.y, leaf.size, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(156, 217, 54, 0.8)';
ctx.fill();
});
ctx.closePath();
setTimeout(update, 30);
}
document.querySelector('input').onchange = (e) => {
treeDepth = e.target.value;
};
drawTree(canvas.width / 2, canvas.height, 50, 0, treeDepth);
update();
</script>
<script>
const slider = document.createElement('input');
slider.type = 'range';
slider.min = 1;
slider.max = 10;
slider.step = 1;
slider.value = 7;
document.body.appendChild(slider);
</script>
</body>
</html>