Kinetic Color Fields

📅 April 17, 2026 🏷️ art
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

📊 视觉感受量化评分

0
0
0
0

💡 AI 提示词

Create a complete artwork for: Kinetic Color Fields

🧠 核心算法要点

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

💻 原始 p5.js 代码

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.