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