← 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>