GEOMETRIC_KALEIDOSCOPE_MORPH
The single web page application featured in this tutorial web page generates a randomized kaleidoscope-like animation which plays continuously (in a looping manner) for indefinitely many cycles. Essentially, the animation consists of multicolored (and semi-transparent) squares and regular triangles spinning counterclockwise around their own centers and orbitting some external point on the canvas (which is colored black for contrast).
Note that a live version of the GEOMETRIC_KALEIDOSCOPE_MORPH application is available to try using immediately from your current web browser at the following web address: https://karlinarayberinger.github.io/KARBYTES_BLOG_APPS_github_hosted_website/GEOMETRIC_KALEIDOSCOPE_MORPH/geometric_kaleidoscope_morph.html
(For information on how this JavaScript application came to be, visit the following plain-text web page: https://raw.githubusercontent.com/karlinarayberinger/KARLINA_OBJECT_extension_pack_46/main/chatgpt_karbytes_20july2025_p0.txt).
To view hidden text inside of the preformatted text boxes below, scroll horizontally.
GEOMETRIC_KALEIDOSCOPE_MORPH Software Application Components
Hyper-Text-Markup-Language_file: https://raw.githubusercontent.com/karlinarayberinger/KARLINA_OBJECT_extension_pack_46/main/geometric_kaleidoscope_morph.html
GEOMETRIC_KALEIDOSCOPE_MORPH Hyper-Text-Markup-Language Code
The following Hyper-Text-Markup-Language (HTML) code defines the user interface component of the GEOMETRIC_KALEIDOSCOPE_MORPH web page application (and also contains all the CSS code and JavaScript code needed to run this application).
Copy the HTML code from the source code file which is linked below into a text editor and save that file as geometric_kaleidoscope_morph.html. Use a web browser such as Firefox to open that HTML file.
(Note that angle brackets which resemble HTML tags (i.e. an “is less than” symbol (i.e. ‘<‘) followed by an “is greater than” symbol (i.e. ‘>’)) displayed on this web page have been replaced (at the source code level of this web page) with the Unicode symbols U+003C (which is rendered by the web browser as ‘<‘) and U+003E (which is rendered by the web browser as ‘>’). That is because the WordPress web page editor or web browser interprets a plain-text version of an “is less than” symbol followed by an “is greater than” symbol as being an opening HTML tag (which means that the WordPress web page editor or web browser deletes or fails to display those (plain-text) inequality symbols and the content between those (plain-text) inequality symbols)).
Hyper-Text-Markup-Language_file: https://raw.githubusercontent.com/karlinarayberinger/KARLINA_OBJECT_extension_pack_46/main/geometric_kaleidoscope_morph.html
<!-- /** * file: geometric_kaleidoscope_morph.html * type: Hyper-Text-Markup-Language * date: 21_JULY_2025 * author: karbytes * license: PUBLIC_DOMAIN */ --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Geometric Kaleidoscope Morph</title> <style> /** * Eliminate all default spacing around the edges of the web page and prevent scrollbars from appearing. * Set the background color of the entire viewport to solid black to provide high contrast for colorful animations. */ html, body { margin: 0; padding: 0; overflow: hidden; background: black; } /** * Ensure the canvas element takes up the full width of the page and behaves like a block-level element, * allowing it to occupy all available space without unexpected gaps. */ canvas { display: block; } </style> </head> <body> <canvas id="canvas"></canvas> <script> // Retrieve the canvas element from the HTML document using its unique ID ("canvas"). // Obtain the 2D rendering context ("ctx") associated with the canvas to enable drawing operations using standard vector graphics functions. // Declare the width and height variables which will later store the current pixel dimensions of the canvas for dynamic layout and scaling calculations. const canvas = document.getElementById("canvas"); const ctx = canvas.getContext("2d"); let width, height; // Define a resize() function which dynamically sets the canvas dimensions to match the current size of the browser window. // This ensures that the visual display fills the entire viewport without scrollbars or clipping artifacts. // Attach the resize() function to the window's resize event listener to automatically adjust the canvas when the user resizes the window. // Immediately invoke resize() once at the beginning of the program to initialize the canvas to the correct size. function resize() { width = canvas.width = window.innerWidth; height = canvas.height = window.innerHeight; } window.addEventListener("resize", resize); resize(); // NUM_SECTORS defines the number of radial symmetry divisions used to mirror shape patterns, // creating a kaleidoscopic visual effect with rotational and reflective repetition. // SHAPE_COUNT determines how many unique polygonal shapes will be animated per sector. // The shapes array is initialized as empty and will later store the randomly generated shape data. const NUM_SECTORS = 16; const SHAPE_COUNT = 60; const shapes = []; // Define a set of vivid base colors (cyan, magenta, yellow, green, red, indigo, and orange). // These hexadecimal values serve as the core palette from which randomized shades are generated // to produce dynamic and visually striking polygonal patterns against a black canvas. const BASE_COLORS = [ '#00ffff', '#ff00ff', '#ffff00', '#00ff00', '#ff0000', '#4b0082', '#ff8000' ]; /** * Define a function named randomShade which takes a hexadecimal color string (baseHex) * as input and returns a randomly adjusted shade of that color as a semi-transparent RGBA string. * * The input string is expected to follow the format "#RRGGBB", where RR, GG, and BB * are two-digit hexadecimal values corresponding to the red, green, and blue channels respectively. * * The parseInt(baseHex.slice(1), 16) expression converts the hex string into an integer. * Bitwise operations extract the red (r), green (g), and blue (b) components from that integer. * * Each color channel is then modified by a random offset in the range [-20, 20] using: * Math.floor(Math.random() * 40 - 20) * * The result of each offset is clamped between 0 and 255 to stay within valid RGB bounds * using Math.max(0, Math.min(255, value)). * * A random opacity value between 0.5 and 1.0 is generated and appended as the alpha (a) channel. * * The returned string is of the format: * "rgba(R, G, B, A)" * * This function introduces subtle variety in color and opacity to create a more organic and * layered visual effect when filling shapes in the canvas animation. */ function randomShade(baseHex) { const color = parseInt(baseHex.slice(1), 16); const r = ((color >> 16) & 0xFF) + Math.floor(Math.random() * 40 - 20); const g = ((color >> 8) & 0xFF) + Math.floor(Math.random() * 40 - 20); const b = (color & 0xFF) + Math.floor(Math.random() * 40 - 20); return `rgba(${Math.max(0, Math.min(255, r))}, ${Math.max(0, Math.min(255, g))}, ${Math.max(0, Math.min(255, b))}, ${Math.random() * 0.5 + 0.5})`; } /** * Define a function named createShape which returns a JavaScript object literal * encoding the attributes of a geometric shape to be rendered in the kaleidoscope animation. * * (When pointCount is 3, the shape is a triangle.) * * (When pointCount is 4, the shape is a square (specifically, a regular quadrilateral)). * * Each shape object includes the following key-value pairs: * * - baseX: The initial horizontal coordinate (in pixels) of the shape’s orbit center, * chosen uniformly at random within the right half of the canvas viewport. * * - baseY: The initial vertical coordinate (in pixels) of the shape’s orbit center, * chosen uniformly at random within the bottom half of the canvas viewport. * * - angleOffset: A random angle in the interval [0, 2π) which determines the initial * phase of the shape’s orbit trajectory. * * - size: The radius of the shape in pixels (i.e. the distance from the shape’s center to a vertex), * randomly selected from the interval [20, 60). * * - speed: A small angular velocity value determining how fast the shape moves * along its circular orbit path, chosen randomly from the interval [0.001, 0.003). * * - orbitRadius: The radius of the circular path along which the shape’s center moves, * randomly selected from the interval [20, 120). * * - color: A semi-transparent RGBA color string chosen by first randomly selecting a base color * from the BASE_COLORS array and then passing it into the randomShade() function to introduce * subtle variation in hue and opacity. * * - pointCount: An integer value representing the number of vertices used to construct * the polygonal shape (i.e. 3 or 4, chosen with equal probability). * * This function is called once for each shape to populate the shapes array, * enabling a dynamic and diverse set of morphing polygons that move with independent speeds, * sizes, orientations, and colors in the kaleidoscopic animation. */ function createShape() { return { baseX: Math.random() * width / 2, baseY: Math.random() * height / 2, angleOffset: Math.random() * Math.PI * 2, size: Math.random() * 40 + 20, speed: Math.random() * 0.002 + 0.001, orbitRadius: Math.random() * 100 + 20, color: randomShade(BASE_COLORS[Math.floor(Math.random() * BASE_COLORS.length)]), pointCount: Math.floor(Math.random() * 2) + 3 }; } // Populate the shapes array with SHAPE_COUNT distinct shape objects. // Each shape is initialized with randomized attributes such as position, size, // color, angular offset, orbit radius, and number of polygonal sides. // This loop sets up the foundational data for the animated geometric pattern. for (let i = 0; i < SHAPE_COUNT; i++) { shapes.push(createShape()); } /** * Define a function named drawRegularPolygonwhich draws a regular polygon * (either a triangle or else a quadrilateral) centered at the point (x, y) on the canvas. * * Parameters: * * - x: The horizontal coordinate (in pixels) of the polygon's center. * * - y: The vertical coordinate (in pixels) of the polygon's center. * * - size: The radius (in pixels) from the center to each vertex of the polygon. * * - angle: The rotation angle (in radians) applied to the entire polygon (with the * premise being that the polygon rotates around its center counterclockwise). * * - points: The number of vertices the polygon should have (e.g. 3 for triangle, 4 for square). * * The function begins by invoking ctx.beginPath() to start a new drawing path. * * Then, for each vertex index i in the interval [0, points): * * - theta is computed as the angle offset for that vertex (i.e. equally spaced around the circle). * * - (px, py) is computed as the Cartesian coordinate of the vertex, * using polar-to-Cartesian conversion relative to the polygon’s center. * * The first vertex is set as the starting point of the path using ctx.moveTo(), * and all subsequent vertices are connected using ctx.lineTo(). * * Once all vertices have been specified, ctx.closePath() connects the final vertex * back to the starting point to complete the polygon. * * Finally, ctx.fill() fills the polygon using the current fillStyle (color and opacity). * * This function provides the geometric foundation for rendering the symmetric, colorful, * rotationally animated triangular patterns used in the kaleidoscope visual. */ function drawRegularPolygon(x, y, size, angle, points) { ctx.beginPath(); for (let i = 0; i < points; i++) { const theta = angle + (i * 2 * Math.PI) / points; const px = x + size * Math.cos(theta); const py = y + size * Math.sin(theta); if (i === 0) ctx.moveTo(px, py); else ctx.lineTo(px, py); } ctx.closePath(); ctx.fill(); } /** * Define a function named drawShape which renders a single polygonal shape * (e.g. triangle or quadrilateral) onto the canvas at a position determined * by the animation time and the shape’s individual motion parameters. * * Parameters: * * - shape: An object literal specifying the geometric and dynamic properties * of the shape to be rendered (as returned by createShape()). * * - t: The current timestamp (the time value passed into the animation loop), * used to determine the phase of the shape's orbit path; a scalar quantity * indicating the number of milliseconds elapsed since the animation started. * * The function computes the shape’s current angle `a` by multiplying * the elapsed time `t` by the shape’s angular velocity `shape.speed`. * * The horizontal (x) and vertical (y) coordinates of the shape’s center are computed * using parametric circular motion equations. The result is that the shape orbits * around its base point (`baseX`, `baseY`) at a constant radius and speed, * with an initial phase offset (`angleOffset`) to introduce asymmetry between shapes. * * The fillStyle of the canvas context is set to the shape’s assigned RGBA color, * which may vary in both hue and transparency. * * The function then invokes drawRegularPolygon() to render the actual geometry * of the shape (e.g. triangle, square) at the computed position and angle. * * This function encapsulates how a shape "animates" over time by rotating around * its origin point, changing orientation, and appearing in one or more mirrored sectors * as part of the kaleidoscopic rendering process. */ function drawShape(shape, t) { const a = t * shape.speed; const x = shape.baseX + Math.cos(a + shape.angleOffset) * shape.orbitRadius; const y = shape.baseY + Math.sin(a + shape.angleOffset) * shape.orbitRadius; ctx.fillStyle = shape.color; drawRegularPolygon(x, y, shape.size, a, shape.pointCount); } /** * Define a function named render which is repeatedly invoked by the web browser’s * animation scheduler (via requestAnimationFrame) to draw each new frame of the * kaleidoscopic animation sequence. * * Parameter: * * - time: The current animation timestamp in milliseconds (automatically provided * by requestAnimationFrame) which serves as the dynamic input for computing shape * positions and orientations. * * (The position of a shape refers to where its center (x,y) is located on the canvas). * * (The orientation of a shape refers to how it is rotated (angle) around its own center point). * * The function begins by clearing the entire canvas to prepare it for the next frame. * * The drawing context is then translated such that the origin (0, 0) aligns with the * center of the canvas viewport. This ensures that rotational symmetry operations * radiate outward from the center. * * A for-loop iterates NUM_SECTORS times to create a rotationally symmetric pattern. * * For each sector index s: * * - The context is rotated by an angle of (s × 2π) ÷ NUM_SECTORS radians to orient * the drawing region toward the appropriate slice of the circle. * * - If the sector index is odd, the context is flipped vertically (reflected across the x-axis) * to create a mirrored pattern effect between adjacent sectors. * * - Each shape in the shapes array is rendered by invoking drawShape() with the current * timestamp to compute the shape’s dynamic position and rotation. * * After drawing all shapes for a given sector, the context state is restored to undo * that sector’s transformations before moving on to the next one. * * Once all sectors have been rendered, the outer transformation is undone. * * Finally, requestAnimationFrame(render) schedules the render function to be * called again for the next animation frame, enabling continuous animation. */ function render(time) { ctx.clearRect(0, 0, width, height); ctx.save(); ctx.translate(width / 2, height / 2); for (let s = 0; s < NUM_SECTORS; s++) { ctx.save(); ctx.rotate((s * Math.PI * 2) / NUM_SECTORS); if (s % 2 === 1) ctx.scale(1, -1); for (const shape of shapes) { drawShape(shape, time); } ctx.restore(); } ctx.restore(); requestAnimationFrame(render); } // Queue the render() function to execute just before the next screen repaint, // enabling smooth, hardware-optimized animation that synchronizes with the browser's refresh rate. // This call continuously loops the animation by re-invoking render() at the end of each frame cycle. requestAnimationFrame(render); </script> </body> </html>
GEOMETRIC_KALEIDOSCOPE_MORPH Interface (screenshot during runtime)
The following is a screenshot image taken of a randomly generated kaleidoscope-like animation.
This web page was last updated on 21_JULY_2025. The content displayed on this web page is licensed as PUBLIC_DOMAIN intellectual property.