画一棵樱桃树
- Published on
- //趣玩前端
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<title>画一颗樱桃树</title>
<style>
* {
margin: 0;
box-sizing: border-box;
overflow: hidden;
}
body {
background: #e6e2ca;
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
body canvas {
box-shadow: 0.2em 0.2em 2em #0008;
border: none;
outline: none;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="https://cdn.jsdelivr.net/processing.js/1.4.8/processing.min.js"></script>
<script>
var sketchProc = function (processingInstance) {
with (processingInstance) {
size(600, 600);
frameRate(60);
smooth();
textAlign(CENTER, CENTER);
textSize(25);
strokeCap(PROJECT);
//used for controlling the animation
var lenBranches = 0,
lenLeaves = 0,
lenFlowers = 0;
//define the tree object/properties
var tree = {
x: 300,
y: 500,
len: 100,
depth: 6,
angle: -90,
branches: [],
leaves: [],
flowers: [],
colors: {
from: color(59, 39, 8),
to: color(145, 108, 49),
},
};
//the recursive function (will be called from within itself)
var addBranch = function (x, y, depth, angle, len) {
//if the depth is zero then end the recursion
if (depth === 0) {
return;
}
//calculate the end points of the branch
var x2 = x + cos((angle * Math.PI) / 180) * len;
var y2 = y + sin((angle * Math.PI) / 180) * len;
//add the new branch to the tree
tree.branches.push({
x1: x,
y1: y,
x2: x2,
y2: y2,
depth: depth,
color: lerpColor(
tree.colors.from,
tree.colors.to,
map(depth, tree.depth, 1, 0, 1)
),
});
//add some random leaves to the branches
if (depth > 0 && depth < tree.depth - 3 && random() < 0.3) {
for (var i = 0; i < 2; i++) {
var l = len * random(0.1, 0.9);
var tx = x + cos((angle * Math.PI) / 180) * l;
var ty = y + sin((angle * Math.PI) / 180) * l;
tree.leaves.push({
x: tx,
y: ty,
diameter: random(5, 10),
color: color(
random(80, 100),
random(150, 180),
random(90, 110)
),
angle: random(angle - 60, angle + 60),
});
}
}
//add some random flowers to the end of the branches
if (
(depth === 1 && random() < 0.5) ||
(depth === 2 && random() < 0.3)
) {
tree.flowers.push({
x: x2,
y: y2,
diameter: depth === 1 ? random(15, 25) : random(10, 15),
color: color(
random(200, 255),
random(60, 100),
random(90, 120)
),
angle: angle,
gap: random(0, 90),
});
}
//reduce the depth (extremely important to end your recursion)
depth--;
var l = len * random(0.6, 0.8);
var x3 = x + cos((angle * Math.PI) / 180) * l;
var y3 = y + sin((angle * Math.PI) / 180) * l;
//call this function recursively
addBranch(
x2,
y2,
depth,
angle - random(10, 50),
len * random(0.75, 0.85)
);
addBranch(
x2,
y2,
depth,
angle + random(10, 50),
len * random(0.75, 0.85)
);
addBranch(
x3,
y3,
depth,
angle + random(-30, 30),
len * random(0.75, 0.85)
);
};
//call the recusive function
addBranch(tree.x, tree.y, tree.depth, tree.angle, tree.len);
draw = function () {
background(230, 226, 202);
noStroke();
fill(50, 30);
ellipse(tree.x, tree.y + 5, 200, 35);
//draw the trees
for (var i = 0; i < lenBranches; i++) {
var branch = tree.branches[i];
//set the stroke opacity based on the branch depth
stroke(branch.color, 50 + branch.depth * 35);
//set the stroke thickness based on the branch depth
strokeWeight(1 + branch.depth);
//draw the branch
line(branch.x1, branch.y1, branch.x2, branch.y2);
}
//used for animating the branches
lenBranches = constrain(lenBranches + 1, 0, tree.branches.length);
//if all the branches are displayed then show the leaves
if (lenBranches === tree.branches.length) {
//draw the leaves
for (var i = 0; i < lenLeaves; i++) {
var leaf = tree.leaves[i];
pushStyle();
noStroke();
fill(leaf.color);
arc(
leaf.x,
leaf.y,
leaf.diameter,
leaf.diameter,
((leaf.angle + 70) * Math.PI) / 180,
((leaf.angle + 290) * Math.PI) / 180
);
popStyle();
}
//used for animating the leaves
lenLeaves = constrain(lenLeaves + 1, 0, tree.leaves.length);
}
//if all the leaves are displayed then show the flowers
if (lenLeaves === tree.leaves.length) {
//draw the flowers
for (var i = 0; i < lenFlowers; i++) {
var flower = tree.flowers[i];
pushStyle();
noStroke();
fill(flower.color);
arc(
flower.x,
flower.y,
flower.diameter,
flower.diameter,
((flower.angle + flower.gap) * Math.PI) / 180,
((flower.angle + 360 - flower.gap) * Math.PI) / 180
);
popStyle();
}
if (++lenFlowers === tree.flowers.length + 1) {
noLoop();
}
}
//display how many branches there are
fill(50, 50);
// text(
// tree.branches.length +
// ' branches, ' +
// tree.leaves.length +
// ' leaves, ' +
// tree.flowers.length +
// ' flowers',
// 300,
// 30
// );
text('点击画一棵樱桃树', 300, 570);
};
mouseClicked = function () {
tree.branches.length = 0;
tree.leaves.length = 0;
tree.flowers.length = 0;
lenBranches = 0;
lenLeaves = 0;
lenFlowers = 0;
tree.angle = random(-100, -80);
addBranch(tree.x, tree.y, tree.depth, tree.angle, tree.len);
loop();
};
}
};
var canvas = document.getElementById('canvas');
var processingInstance = new Processing(canvas, sketchProc);
</script>
</body>
</html>