Skip to content

js+canvas 生成随机[树]

演示

<template>
    <div class="container">
        <canvas ref="canvas" width="100%"></canvas>
        <el-button class="change" @click="generateTree">重新生成</el-button>
    </div>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
const canvas = ref<HTMLCanvasElement>();
// 生成树
const generateTree = () => {
    const cv = canvas.value;
    if (cv) {
        const width = (cv?.parentNode as HTMLDivElement)?.clientWidth;
        const height = window.innerHeight * devicePixelRatio * 0.5;
        cv.width = width;
        cv.height = height;
        //  获取画布
        const ctx = canvas.value?.getContext("2d") as CanvasRenderingContext2D;
        // 清空画布之前的内容
        ctx.clearRect(0, 0, width, height);
        // 更改坐标系
        ctx.translate(width / 2, height);
        ctx.scale(1, -1);
        drawBranch([0, 0], height * 0.15, height * 0.02, 90);
        function drawBranch(
            v0: [number, number],
            length: number,
            thick: number,
            dir: number
        ) {
            if (thick < height * 0.008 && Math.random() < 0.3) {
                return;
            }
            if (thick < height * 0.002) {
                ctx.beginPath();
                ctx.arc(...v0, height * 0.01, 0, 2 * Math.PI);
                ctx.fillStyle = Math.random() < 0.1 ? "#db8418" : "#fff";
                ctx.fill();
                return;
            }
            ctx.beginPath();
            ctx.moveTo(...v0);
            const v1: [number, number] = [
                v0[0] + length * Math.cos((dir * Math.PI) / 180),
                v0[1] + length * Math.sin((dir * Math.PI) / 180),
            ];
            ctx.lineTo(...v1);
            ctx.lineWidth = thick;
            ctx.fillStyle = "#333";
            ctx.lineCap = "round";
            ctx.stroke();
            drawBranch(v1, length * 0.8, thick * 0.8, dir + Math.random() * 30);
            drawBranch(v1, length * 0.8, thick * 0.8, dir - Math.random() * 30);
        }
    }
}
onMounted(() => {
    generateTree()
});
</script>
<style lang="scss" scoped>
.container {
    position: relative;

    canvas {
        background-color: #a1c3a1;
    }

    .change {
        position: absolute;
        top: 10px;
        right: 10px;
    }
}

.dark .container canvas {
    background-color: #394339;
}
</style>