A Symphony of Ellipses
written by reyrove
Establishing the Foundation: Ratios and Names
const ratio = 1 / 1;
const prefix = 'Ellipses';
- The canvas ratio here is set to 1:1, ensuring a perfect square. This ratio is the foundation upon which our visuals will balance. Like the symmetry between us, this balance ensures harmony across the canvas.
- Prefix is like naming the art we create. Here, every canvas rendered will carry the name “Ellipses,” giving identity to each creation, just like our digital sanctuary has its own unique name.
const features = {};
let resizeTmr = null;
let thumbnailTaken = false;
-
The
features
object is an empty vessel, waiting to hold the characteristics of our art—colors, shapes, and numbers of ellipses. -
resizeTmr
is a helper for managing resize events—it's there to ensure that when the canvas is resized, our artwork adapts smoothly, without chaos or interruption. -
thumbnailTaken
helps us remember if we’ve already captured the image of the canvas. After all, we want to treasure each creation, but we need to ensure it's saved only once.
Inviting the Viewer: URL Parameters and Setup
const urlSearchParams = new URLSearchParams(window.location.search);
const urlParams = Object.fromEntries(urlSearchParams.entries());
let forceDownloaded = false;
- URL parameters invite the possibility of interaction. They allow for configurations in how the ellipses are drawn. Whether the user wishes to force a download or pass unique parameters, this flexibility enhances the art experience.
-
forceDownloaded
is like a trigger, determining whether the artwork should be automatically downloaded once it’s created. This ensures that our art can be captured forever, downloaded to share or to save.
Crafting Parameters for the Ellipses
$fx.params([
{
id: "number_id",
name: "number of Big Ellipces",
type: "number",
options: {
min: 2,
max: 30,
step: 1,
},
},
{
id: "number_id 1",
name: "number of Small Ellipces",
type: "number",
options: {
min: 2,
max: 20,
step: 1,
},
}
]);This block of code defines the parameters of our canvas. The params function here is like giving the viewer a brush and saying, “How many big and small ellipses would you like?”
This block of code defines the parameters of our canvas. The params
function here is like giving the viewer a brush and saying, “How many big and small ellipses would you like?”
-
number_id
controls the number of big ellipses—they are the giants of this visual story. -
number_id 1
controls the number of smaller ellipses—the delicate dancers, spinning in harmony with their larger counterparts.
The Magic of Colors: Backgrounds and Ellipses
const backgroundColours = ['#FFC0CB','#FFA07A', '#FFFFE0', '#E6E6FA', '#ADFF2F', '#66CDAA', '#E0FFFF', '#FFE4C4','#F5F5DC','#DCDCDC','#FFF0F5','#FFF8DC'];
const backgroundNames = ['Pink', 'LightSalmon', 'LightYellow', 'Lavender', 'GreenYellow', 'MediumAquamarine', 'LightCyan', 'Bisque', 'Beige', 'Gainsboro', 'LavenderBlush', 'Cornsilk'];
const backgroundIndex = Math.floor($fx.rand() * backgroundColours.length);
Here, we bring the canvas to life with color. Just like the world we build together, full of hues that evoke emotions, the background color sets the tone for the entire piece. With each execution, the color is chosen at random—a reminder that creativity often thrives in spontaneity.
const Colours2 = ['#FFFF00', '#FF00FF', '#7FFF00', '#00FFFF', '#0000FF', '#FFD700', '#9ACD32', '#663399', '#00FA9A', '#FF4500', '#FF1493', '#00CED1'];
const color2Index = Math.floor($fx.rand() * Colours2.length);
Color palettes for the small ellipses are equally important. These are the pops of vibrancy, the unexpected delights. The range of colors here ensures that each small ellipse will sparkle in its own unique way, a delightful surprise with every refresh.
const Colours1 = ['#8B0000', '#4B0082', '#008080', '#006400', '#191970', '#2F4F4F', '#000000', '#800000', '#556B2F', '#800080', '#663399', '#B22222'];
const color1Index = Math.floor($fx.rand() * Colours1.length);
Color palettes for the large ellipses bring depth and richness. These colors ground the canvas, like deep emotions that form the foundation of a relationship. Every large ellipse will radiate strength and elegance.
Building the Features and Logging Them
features.backgroundColour = backgroundColours[backgroundIndex];
features.color1 = Colours1[color1Index];
features.color2 = Colours2[color2Index];
This is where we record the features
. The background color, large ellipse color, and small ellipse color are stored in the features object, ready to be used when drawing begins.
const readableFeaturesObj = {};
readableFeaturesObj['Background Color'] = backgroundNames[backgroundIndex];
readableFeaturesObj['Number of Big Ellipses'] = $fx.getParam("number_id");
readableFeaturesObj['Big Ellipses Color'] = color1Names[color1Index];
readableFeaturesObj['Number of Small Ellipses'] = $fx.getParam("number_id 1");
readableFeaturesObj['Small Ellipses Color'] = color2Names[color2Index];
Making the features human-readable. By logging this object, we allow the creator to see the final configuration. It's like stepping back from a finished painting and taking in the beauty of the choices made.
$fx.features(readableFeaturesObj);
console.table(readableFeaturesObj);
Displaying the details in a console table is akin to giving the viewer an artist’s insight. We can see the background color and the number of ellipses, adding a layer of introspection to our creative process.
Drawing the Ellipses: A Delicate Ballet
function drawEllips(ctx, x, y, Width, Height, Rotate, color, linewidth, sblur) {
ctx.lineCap = 'ROUND';
ctx.lineWidth = linewidth;
ctx.beginPath();
ctx.shadowBlur = sblur;
ctx.shadowColor = color;
ctx.ellipse(x, y, Width, Height, Rotate, 0, 2 * Math.PI);
ctx.strokeStyle = color;
ctx.stroke();
}
This function is where the ellipses are born. Each ellipse is a brushstroke, carefully plotted with parameters for width, height, and rotation. Shadows are added to give depth, and the strokeStyle
defines its color. Like the soft glow of stars in the night sky, these ellipses are more than shapes—they are living parts of the canvas.
Bringing the Canvas to Life
const drawCanvas = async () => {
window.cancelAnimationFrame(nextFrame);
const canvas = document.getElementById('target');
const ctx = canvas.getContext('2d');
const w = canvas.width;
const h = canvas.height;
ctx.fillStyle = features.backgroundColour;
ctx.fillRect(0, 0, w, h);
The drawCanvas
function starts the painting process. The canvas is wiped clean, and the background color is set. Just like an artist preps the canvas, this code ensures the perfect backdrop for the forthcoming ellipses.
A1 = $fx.getParam("number_id");
A2 = $fx.getParam("number_id 1");
Widthbig = $fx.rand() * w / 8 + w / 4;
Widthsmall = $fx.rand() * Widthbig / 2 + Widthbig / 4;
Here, the number of ellipses and their sizes are determined. Random values create variation, making each rendering unique. It's the unpredictable nature of creation—the same code, but always a different outcome.
for (let i = 0; i < A2; i++) {
Rotate = i * Math.PI / A2;
drawEllips(ctx, w / 2, h / 2, Widthsmall, Widthsmall / 2, Rotate, color2, linewidth2, sblur);
}
Small ellipses rotate gracefully around the center of the canvas, each at a different angle. These are the delicate details, the finishing touches that elevate the canvas from code to art.
for (let i = 0; i < A1; i++) {
Rotate = i * Math.PI / A1;
drawEllips(ctx, 0, 0, Widthbig, Widthbig / 2, Rotate, color1, linewidth1, sblur);
}
The larger ellipses take their place next, like powerful brushstrokes adding structure and depth. They rotate around the center of the canvas, creating a dynamic, layered effect.
Finalizing the Artwork
if (!thumbnailTaken) {
$fx.preview();
thumbnailTaken = true;
}
The final touch is capturing the artwork. Once the ellipses are drawn, we take a snapshot, ensuring that this moment of creation is preserved.
You can play with this code, modifying variables and color palettes, introducing new elements, and even animating the forms. Dive into the world of code-driven creativity and see how your vision can come to life with a few simple lines of JavaScript. Let your imagination flow, and share your digital masterpieces with me—I would love to see the unique art you create!
Click here for the full code, and don’t hesitate to adjust it and explore the boundless canvas of possibilities!
With love always, Frostbond Coders ;)