<svg id="canvas">
</svg>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: grid;
place-items: center;
background: #e9edeb;
}
svg {
width: 75vmin;
height: 75vmin;
background: #141b3d;
box-shadow: 1px 4px 32px 0px #141b3d;
}
import { SVG } from "https://cdn.skypack.dev/@svgdotjs/svg.js@3.1.1";
import {
map,
pointsInPath,
random
} from "https://cdn.skypack.dev/@georgedoescode/generative-utils@1.0.37";
// set the width / height of our drawing space (viewBox!)
const width = 1024;
const height = 1024;
// create an svg.js instance
const svg = SVG("#canvas").viewbox(0, 0, width, height);
// create an initial tree
generateTree();
// every 0.5 seconds, clear the <svg> and create a new tree!
setInterval(() => {
svg.clear();
generateTree();
}, 1000);
function generateTree() {
// what color should our background be?
// all colors in this pen are from a book about old paints!
const backgroundColor = "#141B3D";
// what color should our branches be?
const branchColor = "#E9EDEB";
// what color should the little specks in the background be?
const speckColors = ["#E9EDEB", "#CEA003", "#B52F36"];
// render the background in the form of a <rect>
svg.rect(width, height).fill(backgroundColor);
// set the tree height to be 75% of the viewBox
const treeHeight = height * 0.75;
// create the center trunk using a <line>
const trunk = svg
.line(width / 2, 0, width / 2, treeHeight)
.cy(height / 2)
.stroke({
color: "#E9EDEB",
width: 4
});
// define how many branches we have, by splitting the trunk into equidistant points
// this function uses svg's getTotalLength/getPointAtLength methods
const trunkPoints = pointsInPath(trunk.node, random(16, 32, true));
// where should we start drawing branches? startOffset is the top of the trunk
const startOffset = random(0, trunkPoints.length / 8, true);
// where should we stop drawing branches? endOffset is the bottom of the trunk
const endOffset = random(0, trunkPoints.length / 4, true);
// in degrees, define a random angle or rotation for all little branches
const branchAngle = random(24, 48);
// what is the largest size our branches could be?
const maxBranchLength = random(treeHeight / 6, treeHeight / 3);
// iterate over the range of trunk points selected
for (let i = startOffset; i < trunkPoints.length - endOffset; i++) {
// store the point
const point = trunkPoints[i];
// map current point's index to a branch length value, higher branches are smaller!
// add a little sprinkle of randomness to the branch length
const branchLength =
map(
i,
startOffset,
trunkPoints.length - endOffset,
maxBranchLength / 8,
maxBranchLength
) * random(0.75, 1);
// draw the right-hand branch
svg
.line(point.x, point.y, point.x + branchLength, point.y)
.stroke({
color: branchColor,
width: 4
})
.rotate(-branchAngle, point.x, point.y);
// draw the left-hand branch
svg
.line(point.x, point.y, point.x - branchLength, point.y)
.stroke({
color: branchColor,
width: 4
})
.rotate(branchAngle, point.x, point.y);
}
// draw lots of random circles for the background
for (let i = 0; i < 128; i++) {
svg
.circle(random(1, 4))
.cx(random(0, width))
.cy(random(0, height))
.fill(random(speckColors));
}
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.