Kinetic Color Fields

📅 April 17, 2026 🏷️ art
worth-a-look Kinetic Art Generative Art Abstract Art Perlin Noise Color Fields Dynamic Systems Animation Organic Patterns
Generated by GridFlow AI | Tags: Kinetic Art, Generative Art, Abstract Art, Perlin Noise, Color Fields, Dynamic Systems, Animation, Organic Patterns

💡 AI 提示词

Create a complete artwork for: Kinetic Color Fields

🔧 核心算法要点

  1. A responsive grid of circular elements is established, adapting dynamically to window size changes.
  2. Each circle's color (Hue, Saturation, Brightness) is determined by multiple, distinct Perlin noise functions.
  3. The Perlin noise inputs for color are continuously animated along the Z-axis, creating smooth, evolving color transitions across the field.
  4. The size of each circle is controlled by a separate Perlin noise function, providing spatial variation in scale.
  5. An additional global sine-wave-based pulsation is applied to all circles, introducing a rhythmic, breathing motion across the entire grid.
  6. HSB color mode is utilized to facilitate intuitive control over color attributes and achieve smooth, vibrant transitions.

🎨 原始代码

var sketch = function(p) {
    let cols, rows;
    let cellWidth, cellHeight;
    let baseNoiseScale = 0.03; // Base scale for Perlin noise coordinates
    let timeSpeed = 0.002; // Speed of overall time evolution
    let maxCellSizeRatio = 0.9; // Max size of circle relative to cell
    let minCellSizeRatio = 0.3; // Min size of circle relative to cell
    let targetCols = 30; // Desired number of columns, scales responsively

    p.setup = function() {
        let container = document.getElementById('p5-wrapper'); p.createCanvas(container.offsetWidth, container.offsetHeight).parent('p5-wrapper');
        p.colorMode(p.HSB, 360, 100, 100); // Use HSB for intuitive color manipulation
        p.noStroke(); // No borders for the circles
        p.updateGridDimensions(); // Initialize grid dimensions
    };

    // Function to recalculate grid dimensions based on window size
    p.updateGridDimensions = function() {
        cellWidth = p.width / targetCols;
        cols = targetCols;
        rows = p.ceil(p.height / cellWidth); // Maintain cell aspect ratio, ensuring full vertical fill
        cellHeight = p.height / rows; // Adjust cellHeight to perfectly fill canvas
    };

    p.draw = function() {
        p.background(0); // Black background for striking contrast

        let time = p.millis() * timeSpeed; // Global time variable for animation

        for (let i = 0; i < cols; i++) {
            for (let j = 0; j < rows; j++) {
                let x = i * cellWidth + cellWidth / 2;
                let y = j * cellHeight + cellHeight / 2;

                // Perlin noise for color variation (Hue, Saturation, Brightness)
                // Using different noise offsets and speeds for each component for rich, complex transitions
                let hueVal = p.noise(i * baseNoiseScale * 0.8, j * baseNoiseScale * 0.8, time * 0.5);
                let satVal = p.noise(i * baseNoiseScale * 1.2, j * baseNoiseScale * 1.2, time * 0.8 + 100); // +100 offset for different noise path
                let briVal = p.noise(i * baseNoiseScale * 0.9, j * baseNoiseScale * 0.9, time * 0.7 + 200); // +200 offset for different noise path

                // Map noise values to HSB ranges
                let h = p.map(hueVal, 0, 1, 0, 360);
                let s = p.map(satVal, 0, 1, 60, 100); // Keep saturation relatively high for vibrancy
                let b = p.map(briVal, 0, 1, 70, 100); // Keep brightness relatively high

                p.fill(h, s, b);

                // Perlin noise for size variation, creating dynamic forms
                let sizeNoiseX = i * baseNoiseScale * 1.5;
                let sizeNoiseY = j * baseNoiseScale * 1.5;
                let sizeNoiseZ = time * 1.2 + 300; // Faster time evolution for size changes
                let sizeVal = p.noise(sizeNoiseX, sizeNoiseY, sizeNoiseZ);

                // Map noise value to a base size ratio within min/max constraints
                let baseSize = p.map(sizeVal, 0, 1, minCellSizeRatio, maxCellSizeRatio);

                // Add a global, rhythmic pulsation effect for a kinetic feel
                // Sine wave provides smooth oscillation, offset by grid position for a ripple effect
                let globalPulsation = p.sin(time * 2 + (i + j) * 0.1) * 0.2 + 0.8; // Range ~0.6 to 1.0
                
                // Calculate final size based on base size and pulsation
                let finalSize = cellWidth * baseSize * globalPulsation;

                p.ellipse(x, y, finalSize, finalSize);
            }
        }
    };

    // Recalibrate canvas and grid when window is resized
    p.windowResized = function() {
        let container = document.getElementById('p5-wrapper'); p.resizeCanvas(container.offsetWidth, container.offsetHeight);
        p.updateGridDimensions();
    };
};

new p5(sketch);

✨ AI 艺术解读

Kinetic Color Fields invites contemplation into a realm where color and motion converge in an organic dance. The continuously shifting hues and pulsating forms evoke a sense of living energy, like a vast, breathing mosaic or the undulating surface of an alien ocean. This artwork explores the subtle complexities that emerge from simple algorithmic rules, creating a meditative yet dynamic visual experience that hints at the ephemeral beauty of natural phenomena and the unseen forces that shape our world.

📝 补充说明

  • Using multiple Perlin noise instances with different offsets and speeds for hue, saturation, brightness, and size creates richer, less predictable variations than a single noise source.
  • The `p.HSB` color mode is crucial for this type of artwork, allowing direct manipulation of color components for smooth, vibrant transitions without falling into muddy RGB values.
  • Careful tuning of `baseNoiseScale` and `timeSpeed` parameters significantly impacts the artwork's character, dictating the granularity of patterns and the overall pace of evolution.
  • The use of `p.ceil` for calculating `rows` and then adjusting `cellHeight` ensures the grid perfectly fills the canvas vertically, avoiding partial cells or awkward gaps at the bottom.