A while ago I was playing with some basic trees drawn in Canvas using JavaScript. The longer I played, the stranger the shapes got. Here’s my experiment below, along with some code explanations.
Scroll down to see the final result.
This article is part of the JavaScript Canvas series where I post experiments, JavaScript generative art, visualizations, Canvas animations, code snippets and how-to’s.
Two objects – Branch
and BranchCollection
– are required. The information of the branch currently being drawn is stored in the Branch
object, while all branches are stored in BranchCollection
.
First, I set the initial settings for the Canvas:
var width = window.innerWidth;
var height = window.innerHeight;
var canvas = document.getElementById('canvastree');
canvas.width = width;
canvas.height = height;
I then set the number and radius of the initial branch:
// Set the initial number
var n = 2 + Math.random() * 3;
// Set the initial radius
var initialRadius = width / 50;
I then create a new BranchCollection
object to place all branches:
branches = new BranchCollection();
The BranchCollection
object here has the following methods:
add()
: add a new elementremove()
: removes an elementprocess()
: For each element in the collection, call the element’s own processing method in turn
For the created BranchCollection
object, I add the initial branches in turn and initialize them:
for (var i = 0; i < n; i++) {
branch = new Branch();
// Based on the midpoint of the canvas, the left and right occupy the width of an initialRadius
// Calculate the initial x coordinate branch.x according to the serial number
i = width / 2 - initialRadius + i * 2 * initialRadius / n;
branch.radius = initialRadius;
// Add the new branch to the set to
branches.add(branch);
}
Branch objects have these properties:
x
,y
: coordinate valuesradius
: Each branch displayed on the screen is actually a combination of circles with gradually decreasing radius,radius
is the radius of the circleangle
: the angle at which the branch extends upward from the bottom, the initial value is PI/2speed
: a parameter that controls the speed at which the branch extendsgeneration
: The current branch is the first generation. When a fork occurs, the generation will increase by one.distance
: the length of the current branch, used to control the probability of bifurcationfillStyle
,shadowColor
,shadowBlur
: drawing parameters
The methods of the Branch
object are:
process()
: The main processing part, calling several other methodsdraw()
: Draw a circle at the current coordinatesiterate()
: Extend the branch up, update the coordinate value, reduce the radius, and add a random value to the anglesplit()
: According to the distance value to determine whether the current can be forked, if possible, create severalBranch
objects to join the collection, and delete the current parent objectdie()
: Determine whether the current object needs to be deleted
Finally, the setInterval()
function is used to generate an image, and all branches are traversed every time interval to draw graphics, update coordinates, generate offspring, etc.
var interval = setInterval(function () {
// Process each element in the collection
branches.process();
if (branches.branches.length == 0 ) {
clearInterval(interval);
}
}, 20);
See the final result below.
See the Pen Canvas: Strange, Creepy Cables by Ciprian (@ciprian) on CodePen.