### Highlights Configuration Examples Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/configuration.md Examples showing how to configure the `highlights` parameter with single, multiple, or no highlight colors. ```swift FluidGradient( blobs: [.red, .blue], highlights: [.yellow] // Single highlight over base layer ) FluidGradient( blobs: [.red, .blue, .green], highlights: [.yellow, .orange, .pink] // Same count as blobs ) FluidGradient( blobs: [.red, .blue], highlights: [] // No highlights, only base layer ) ``` -------------------------------- ### Speed Configuration Examples Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/configuration.md Examples demonstrating how to set the animation speed, including adjusting it dynamically and disabling animation. ```swift @State var animationSpeed = 1.0 FluidGradient( blobs: [.red, .blue], speed: animationSpeed ) // Adjust speed with a slider Slider(value: $animationSpeed, in: 0.0...5.0) // Stop animation FluidGradient(blobs: [.red], speed: 0) ``` -------------------------------- ### Blur Configuration Examples Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/configuration.md Examples illustrating the effect of different `blur` values on the softness of blob edges. ```swift FluidGradient( blobs: [.red, .blue], blur: 0.0 // Sharp blob edges ) FluidGradient( blobs: [.red, .blue], blur: 1.5 // Very soft, blended appearance ) ``` -------------------------------- ### Blobs Configuration Examples Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/configuration.md Examples demonstrating how to configure the `blobs` parameter with different numbers of colors for the base layer. ```swift FluidGradient(blobs: [.red]) // Single blob FluidGradient(blobs: [.red, .green, .blue]) // Three blobs FluidGradient(blobs: [.red, .green, .blue, .yellow, .pink, .purple]) // Six blobs ``` -------------------------------- ### Example Usage of displace() in BlobLayer Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/CGPoint+Extensions.md Demonstrates how to use the `displace(by:)` method to set the start and end points for a radial blob gradient. ```swift let center = CGPoint(x: 0.5, y: 0.5) let radius = CGPoint(x: 0.2, y: 0.15) let edge = center.displace(by: radius) // edge.x = 0.7, edge.y = 0.65 // Used in BlobLayer initialization: let blobLayer = BlobLayer(color: .red) blobLayer.startPoint = center // Center of blob blobLayer.endPoint = center.displace(by: radius) // Edge of radial gradient ``` -------------------------------- ### Integration Example in a UIViewController Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/ResizableLayer.md Shows how to integrate FluidGradientView, which internally uses ResizableLayer, into a UIKit view controller. The example demonstrates setting up the view and its frame to trigger resizing. ```swift import FluidGradient import UIKit class MyViewController: UIViewController { let gradientView = FluidGradientView( blobs: [.red, .blue], highlights: [.yellow] ) override func viewDidLoad() { super.viewDidLoad() view.addSubview(gradientView) // gradientView.baseLayer is a ResizableLayer with BlobLayer sublayers // When gradientView resizes, baseLayer and highlightLayer auto-resize // When baseLayer/highlightLayer resize, BlobLayers auto-resize } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // Set frame (triggers layoutSublayers in ResizableLayer) gradientView.frame = view.bounds } } ``` -------------------------------- ### FluidGradient Initialization with Colors Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/types.md Example of initializing FluidGradient using an array of SwiftUI Color types for blobs. Ensure SwiftUI is imported. ```swift let colors: [Color] = [.red, .green, .blue, .yellow] FluidGradient(blobs: colors) ``` -------------------------------- ### SwiftUI View with Fluid Gradient Source: https://github.com/cindori/fluidgradient/blob/main/README.md Integrate the FluidGradient into your SwiftUI app by initializing it with desired blob and highlight colors, speed, and blur. This example shows a basic setup with predefined colors. ```swift import SwiftUI import FluidGradient struct ContentView: View { var body: some View { FluidGradient(blobs: [.red, .green, .blue], highlights: [.yellow, .orange, .purple], speed: 1.0, blur: 0.75) .background(.quaternary) } } ``` -------------------------------- ### Default FluidGradient Initialization Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/configuration.md Initialize FluidGradient with minimal configuration, using default values for highlights, speed, and blur. This is useful for a quick setup. ```swift FluidGradient(blobs: [.red]) // Uses all defaults // blobs: [.red] // highlights: [] // speed: 1.0 // blur: 0.75 ``` -------------------------------- ### ResizableLayer Usage Example Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/ResizableLayer.md Demonstrates how to use ResizableLayer by adding BlobLayers as sublayers. When the baseLayer's frame is updated, all its sublayers automatically resize to match. ```swift let baseLayer = ResizableLayer() baseLayer.addSublayer(BlobLayer(color: .red)) baseLayer.addSublayer(BlobLayer(color: .green)) // When baseLayer is resized, all sublayers automatically resize baseLayer.frame = CGRect(x: 0, y: 0, width: 300, height: 400) // Both BlobLayers now have frame (0, 0, 300, 400) ``` -------------------------------- ### BlobLayer Initialization and Animation Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/BlobLayer.md Demonstrates how to initialize a BlobLayer, add it to a UIView's layer, resize it, start an animation, change its color, and restart the animation with a different speed. Requires importing FluidGradient and UIKit. ```swift import FluidGradient import UIKit let container = UIView() let blobLayer = BlobLayer(color: .red) container.layer.addSublayer(blobLayer) // Resize blob to match container blobLayer.frame = container.bounds // Start animation blobLayer.animate(speed: 1.0) // Change color blobLayer.set(color: .blue) // Animate again with different speed DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { blobLayer.animate(speed: 2.0) } ``` -------------------------------- ### macOS FluidGradient Path Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/architecture.md Illustrates the rendering path for FluidGradient on macOS, starting from the FluidGradient struct down to the CALayerDelegate methods. ```text FluidGradient ↓ Representable: NSViewRepresentable ↓ makeNSView() → FluidGradientView ↓ FluidGradientView.wantsLayer = true ↓ layer: ResizableLayer ↓ CALayerDelegate methods ↓ Autoresizing handles frame changes ``` -------------------------------- ### Example Usage of capped() in BlobLayer Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/CGPoint+Extensions.md Shows how to use the `capped()` method to ensure a randomly generated position stays within the [0, 1] bounds for a blob. ```swift let position = CGPoint(x: 1.5, y: -0.2) let capped = position.capped() // capped.x = 1.0, capped.y = 0.0 // Used in BlobLayer.newPosition(): let randomPos = CGPoint(x: CGFloat.random(in: 0.0...1.0), y: CGFloat.random(in: 0.0...1.0)) let safePos = randomPos.capped() // Ensures [0,1] bounds ``` -------------------------------- ### SwiftUI App with FluidGradient Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Integrate FluidGradient into your SwiftUI app's main structure. Ensure you import both SwiftUI and FluidGradient. This example shows how to layer the gradient behind other content. ```swift import SwiftUI import FluidGradient @main struct MyApp: App { var body: some Scene { WindowGroup { ZStack { FluidGradient( blobs: [.red, .green, .blue], highlights: [.yellow], speed: 1.0, blur: 0.75 ) .ignoresSafeArea() VStack { Text("Hello, World!") .font(.largeTitle) .foregroundColor(.white) } } } } } ``` -------------------------------- ### BlobLayer animate() Method Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/CGPoint+Extensions.md Demonstrates how `displace()` is used within the `animate()` method of BlobLayer to set the gradient's end point relative to its start point. ```swift // BlobLayer.animate(speed:) uses displace() func animate(speed: CGFloat) { // ... let position = newPosition() let radius = newRadius() // Set gradient center and edge self.startPoint = position self.endPoint = position.displace(by: radius) // Displace from center // ... } ``` -------------------------------- ### Blur Calculation Example Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Calculates the blur radius based on a blur value and a blur factor. The blur value is typically derived from the view's dimensions. ```swift let blurRadius = pow(blurValue, blur) // where blurValue = min(frame.width, frame.height) ``` -------------------------------- ### displace(by:) Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/CGPoint+Extensions.md Builds a new point by adding a displacement vector to the current point. This is useful for calculating the end point of radial gradients by displacing from the start point. ```APIDOC ## displace(by:) ### Description Builds a new point by adding a displacement vector to the current point. ### Method func displace(by: CGPoint = .init(x: 0.0, y: 0.0)) -> CGPoint ### Parameters #### Path Parameters - **point** (CGPoint) - Required - Displacement vector to add to this point. ### Returns A new `CGPoint` with coordinates `(self.x + point.x, self.y + point.y)`. ### Example ```swift let center = CGPoint(x: 0.5, y: 0.5) let radius = CGPoint(x: 0.2, y: 0.15) let edge = center.displace(by: radius) // edge.x = 0.7, edge.y = 0.65 // Used in BlobLayer initialization: let blobLayer = BlobLayer(color: .red) blobLayer.startPoint = center // Center of blob blobLayer.endPoint = center.displace(by: radius) // Edge of radial gradient ``` ``` -------------------------------- ### Check Animation State Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Retrieves the first BlobLayer from the base layer's sublayers and prints its start point and any associated animations. Helps in inspecting the current animation state of a blob. ```swift let blobLayer = view.baseLayer.sublayers?.first as? BlobLayer print(blobLayer?.startPoint) print(blobLayer?.animations()) ``` -------------------------------- ### FluidGradient with Highlights Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/INDEX.md Initialize FluidGradient with both base blob colors and overlay highlight colors. ```swift FluidGradient( blobs: [.red, .blue], highlights: [.yellow, .orange] ) ``` -------------------------------- ### Basic FluidGradient Initialization Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/INDEX.md Initialize FluidGradient with a required array of base blob colors. ```swift FluidGradient(blobs: [.red, .green, .blue]) ``` -------------------------------- ### Basic FluidGradient Usage in SwiftUI Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/FluidGradient.md Demonstrates how to integrate FluidGradient into a SwiftUI view hierarchy, applying it as a background with custom colors and effects. ```swift import SwiftUI import FluidGradient struct ContentView: View { var body: some View { ZStack { FluidGradient( blobs: [.red, .green, .blue], highlights: [.yellow, .orange], speed: 1.0, blur: 0.75 ) .ignoresSafeArea() VStack { Text("My App") .font(.largeTitle) .foregroundColor(.white) } } } } ``` -------------------------------- ### Displace CGPoint by a Vector Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/CGPoint+Extensions.md Adds a displacement vector to a CGPoint to create a new point. Useful for calculating gradient endpoints relative to a starting point. ```swift func displace(by point: CGPoint = .init(x: 0.0, y: 0.0)) -> CGPoint { return CGPoint(x: self.x + point.x, y: self.y + point.y) } ``` -------------------------------- ### Initialize FluidGradient with SwiftUI Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Basic initialization of FluidGradient within a SwiftUI View. Requires importing SwiftUI and FluidGradient. ```swift import SwiftUI import FluidGradient struct ContentView: View { var body: some View { FluidGradient(blobs: [.red, .green, .blue]) } } ``` -------------------------------- ### FluidGradient Constructor Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Initializes a new FluidGradient with specified colors, highlights, speed, and blur. ```APIDOC ## FluidGradient Constructor ### Description Initializes a new FluidGradient instance. ### Parameters - **blobs** ([Color]) - Required - The array of colors to form the gradient. - **highlights** ([Color]) - Optional - An array of highlight colors. Defaults to an empty array. - **speed** (CGFloat) - Optional - The speed of the gradient animation. Defaults to 1.0. - **blur** (CGFloat) - Optional - The blur effect applied to the gradient. Defaults to 0.75. ``` -------------------------------- ### FluidGradient Initialization Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/INDEX.md Initializes the FluidGradient view with specified blob colors, optional highlights, animation speed, and blur effect. ```APIDOC ## `init(blobs:highlights:speed:blur:)` ### Description Initializes the FluidGradient view with specified blob colors, optional highlights, animation speed, and blur effect. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Method `init` ### Endpoint N/A (Swift struct initializer) ### Parameters - **blobs** ([`Color`]) - Required - An array of colors to be used for the blobs. - **highlights** ([`Color`]) - Optional - An array of colors for highlights. - **speed** (`CGFloat`) - Optional - The speed of the animation. Defaults to 1.0. - **blur** (`CGFloat`) - Optional - The blur effect applied to the gradient. Defaults to 0.75. ### Request Example ```swift let gradient = FluidGradient(blobs: [.red, .blue], speed: 0.5, blur: 0.5) ``` ### Response #### Success Response An initialized `FluidGradient` view. #### Response Example N/A (Initializer) ``` -------------------------------- ### FluidGradient Initializer Parameters Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/FluidGradient.md Defines the parameters for creating a FluidGradient view, including base colors, highlight colors, animation speed, and blur radius. ```swift public init(blobs: [Color], highlights: [Color] = [], speed: CGFloat = 1.0, blur: CGFloat = 0.75) ``` -------------------------------- ### FluidGradientView Initializer Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/FluidGradientView.md Initializes a FluidGradientView with specified blob colors, highlight colors, and animation speed. ```APIDOC ## Initializer `init(blobs: [Color], highlights: [Color], speed: CGFloat)` ### Description Initializes a `FluidGradientView` with an array of colors for the base blob animation, an array of colors for the highlight layer, and a speed multiplier for the animation. ### Parameters #### Parameters - **blobs** (`[Color]`) - Optional - `[]` - Array of colors for base blob layer animation. - **highlights** (`[Color]`) - Optional - `[]` - Array of colors for highlight layer with overlay blend mode. - **speed** (`CGFloat`) - Optional - `1.0` - Animation speed multiplier. Must be greater than 0. ### Initialization Behavior - Initializes `baseLayer` and `highlightLayer` as `ResizableLayer` instances. - Applies `CIOverlayBlendMode` composite filter to highlight layer. - On macOS: Sets `wantsLayer = true`, configures layer delegate, and enables frame change notifications. - On iOS: Adds layers directly to the view's layer. - Calls `create(_:layer:)` for both blobs and highlights. - Schedules animation start on the main dispatch queue. ### Required Initializer ```swift required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } ``` **Note:** The view does not support Interface Builder or storyboard initialization. ``` -------------------------------- ### Initialize FluidGradientView Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/configuration.md Use this initializer to set the base blob colors, highlight colors, and animation speed when creating a FluidGradientView instance directly. ```swift init(blobs: [Color] = [], highlights: [Color] = [], speed: CGFloat = 1.0) ``` -------------------------------- ### ResizableLayer Methods Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Methods for handling layout updates in resizable layers. ```APIDOC ## ResizableLayer Methods ### layoutSublayers #### Description Overrides the default layoutSublayers method to handle layout adjustments. #### Note This method is part of the Core Animation layer lifecycle. ``` -------------------------------- ### Use FluidGradient as a Full Screen Background Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Implement a full-screen gradient background by placing FluidGradient in a ZStack and using '.ignoresSafeArea()'. Content can be overlaid. ```swift ZStack { FluidGradient(blobs: [.red, .blue]) .ignoresSafeArea() // Your content VStack { Text("My App") } } ``` -------------------------------- ### macOS CALayerDelegate and NSViewLayerContentScaleDelegate Extension Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/FluidGradientView.md Ensures correct rendering at high DPI displays by handling content scale inheritance. ```APIDOC ## `FluidGradientView` Extension for `CALayerDelegate`, `NSViewLayerContentScaleDelegate` ### Description Ensures correct rendering at high DPI displays by returning `true` for content scale inheritance. ### Methods #### `layer(_ layer: CALayer, shouldInheritContentsScale newScale: CGFloat, from window: NSWindow) -> Bool` - **layer** (CALayer) - The layer being configured. - **newScale** (CGFloat) - The new content scale factor. - **window** (NSWindow) - The window the layer belongs to. ### Returns `true` to inherit the content scale, `false` otherwise. ### Signature `public func layer(_ layer: CALayer, shouldInheritContentsScale newScale: CGFloat, from window: NSWindow) -> Bool` ``` -------------------------------- ### iOS Lifecycle Method Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/FluidGradientView.md This method is specific to the iOS environment and handles view layout updates. ```APIDOC ## `layoutSubviews()` ### Description Resizes `baseLayer` and `highlightLayer` frames to match view bounds. Calls `updateBlur()` to recalculate blur based on new dimensions. ### Signature `public override func layoutSubviews()` ``` -------------------------------- ### macOS Lifecycle Methods Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/FluidGradientView.md These methods are specific to the macOS environment and handle view lifecycle events. ```APIDOC ## `viewDidMoveToWindow()` ### Description Sets layer content scale from window backing scale factor and calls `updateBlur()`. ### Signature `public override func viewDidMoveToWindow()` ## `resize(withOldSuperviewSize:)` ### Description Updates blur value when view size changes. ### Signature `public override func resize(withOldSuperviewSize oldSize: NSSize)` ``` -------------------------------- ### FluidGradient Import Statements Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Essential import statements for using the FluidGradient library and its dependencies. ```swift import FluidGradient // Main module import SwiftUI // For Color, View, @State import Combine // For AnyCancellable (internal) import CoreAnimation // For CALayer, CAGradientLayer (internal) ``` -------------------------------- ### Create a Static Gradient (No Animation) Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Use this pattern to display a gradient without any animation. Set the 'speed' parameter to 0. ```swift FluidGradient( blobs: [.red, .blue], speed: 0 // No animation ) ``` -------------------------------- ### FluidGradientView Methods Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/INDEX.md Methods for creating, updating blob layers, and configuring animation speed within FluidGradientView. ```APIDOC ## `FluidGradientView` Methods ### Description Provides methods for managing blob layers and animation properties within the FluidGradient system. ### Methods #### `create(_:layer:)` ##### Description Creates or updates blob layers within the FluidGradientView. ##### Parameters - **(unspecified)** - Description for the first parameter. - **layer** - Description for the layer parameter. #### `update(speed:)` ##### Description Updates the animation speed of the FluidGradientView. ##### Parameters - **speed** (`CGFloat`) - The new speed for the animation. ``` -------------------------------- ### Spring Animation Parameters Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/architecture.md Lists the parameters used for CASpringAnimation, highlighting their dependence on the 'speed' variable. ```swift mass = 10 / speed damping = 50 duration = 1 / speed fillMode = .forwards isRemovedOnCompletion = false ``` -------------------------------- ### FluidGradientView Methods Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Methods for creating and updating FluidGradientView instances. 'create' sets the colors and layer, while 'update' adjusts the animation speed. ```swift public func create(_ colors: [Color], layer: CALayer) public func update(speed: CGFloat) ``` -------------------------------- ### FluidGradient Initializer Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/FluidGradient.md Initializes a FluidGradient view with specified colors, animation speed, and blur effects. This is the primary way to create an animated fluid gradient in your SwiftUI application. ```APIDOC ## FluidGradient Initializer ### Description Initializes a FluidGradient view with specified colors, animation speed, and blur effects. This is the primary way to create an animated fluid gradient in your SwiftUI application. ### Method `init` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **blobs** (`[Color]`) - Required - Array of colors for the base blob layer. These are the primary gradient colors that animate. Minimum of 1 color required. - **highlights** (`[Color]`) - Optional - Array of colors for the highlight layer, rendered with overlay blend mode. Creates unique color interactions with base blobs. Defaults to `[]`. - **speed** (`CGFloat`) - Optional - Animation speed multiplier. Controls how fast blobs animate between positions. Values greater than 0; default 1.0 is normal speed. - **blur** (`CGFloat`) - Optional - Blur radius exponent applied to the gradient. Controls the softness of blob edges. Typical range 0.0–1.0; values determine smoothness of the effect. Defaults to `0.75`. ### Return Type Returns a SwiftUI `View` that renders the animated fluid gradient. ### Example ```swift import SwiftUI import FluidGradient struct ContentView: View { var body: some View { ZStack { FluidGradient( blobs: [.red, .green, .blue], highlights: [.yellow, .orange], speed: 1.0, blur: 0.75 ) .ignoresSafeArea() VStack { Text("My App") .font(.largeTitle) .foregroundColor(.white) } } } } ``` ``` -------------------------------- ### FluidGradientView Methods Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Methods for managing the FluidGradient view, including creation and updates. ```APIDOC ## FluidGradientView Methods ### create #### Description Creates or updates the gradient with the given colors and layer. #### Parameters - **colors** ([Color]) - Required - The array of colors for the gradient. - **layer** (CALayer) - Required - The Core Animation layer to apply the gradient to. ``` ```APIDOC ## FluidGradientView Methods ### update #### Description Updates the animation speed of the gradient. #### Parameters - **speed** (CGFloat) - Required - The new speed for the gradient animation. ``` -------------------------------- ### Create a Gradient with Highlights Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Add highlights to the gradient by providing an array of colors to the 'highlights' parameter, alongside 'speed' and 'blur'. ```swift FluidGradient( blobs: [.red, .green], highlights: [.yellow, .orange], speed: 1.0, blur: 0.75 ) ``` -------------------------------- ### create(_:layer:) Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/FluidGradientView.md Creates or updates blob layers for a given set of colors on a target layer. It manages the addition, removal, and color updates of `BlobLayer` instances. ```APIDOC ## create(_:layer:) ### Description Creates blob layers for given colors or updates existing ones. ### Method `create(_ colors: [Color], layer: CALayer)` ### Parameters #### Path Parameters * **colors** (`[Color]`) - Required - Array of colors to create blobs for. * **layer** (`CALayer`) - Required - Target layer (typically `baseLayer` or `highlightLayer`). ### Behavior: - If `colors.count < sublayer.count`: Removes excess sublayers from the end - If `colors.count > sublayer.count`: Creates new `BlobLayer` instances and adds them - If indices match: Updates existing `BlobLayer` colors via `set(color:)` - Each blob layer is a radial gradient layer with randomized position and size ### Request Example: ```swift let view = FluidGradientView(blobs: [], highlights: []) view.create([.red, .green, .blue], layer: view.baseLayer) view.create([.yellow, .orange], layer: view.highlightLayer) ``` ``` -------------------------------- ### Create a Gradient with Sharp Edges (No Blur) Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md To make the gradient edges sharp and distinct, set the 'blur' parameter to 0.0. ```swift FluidGradient( blobs: [.red, .blue], blur: 0.0 // No blur ) ``` -------------------------------- ### macOS CALayerDelegate and NSViewLayerContentScaleDelegate Extension Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/FluidGradientView.md This extension for `FluidGradientView` on macOS implements layer delegate methods to ensure correct content scaling on high-DPI displays by returning true for scale inheritance. ```swift extension FluidGradientView: CALayerDelegate, NSViewLayerContentScaleDelegate { public func layer(_ layer: CALayer, shouldInheritContentsScale newScale: CGFloat, from window: NSWindow) -> Bool { return true } } ``` -------------------------------- ### macOS Lifecycle Methods for FluidGradientView Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/FluidGradientView.md Implement these methods to manage view lifecycle events on macOS. `viewDidMoveToWindow` handles layer content scale, while `resize` updates blur on size changes. ```swift public override func viewDidMoveToWindow() public override func resize(withOldSuperviewSize oldSize: NSSize) ``` -------------------------------- ### Create a Gradient with Fast Animation Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Achieve faster animation for the gradient by setting the 'speed' parameter to a value greater than 1.0. ```swift FluidGradient( blobs: [.red, .blue], speed: 2.0 // Double speed ) ``` -------------------------------- ### set(color:) Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/BlobLayer.md Sets the blob's color gradient using a SwiftUI Color. This method configures a three-stop gradient that transitions from opaque to transparent. ```APIDOC ## set(color:) ### Description Sets the blob's color gradient. This method takes a SwiftUI `Color` and configures a gradient that transitions from the specified color to transparent at the edges. ### Method Signature ```swift func set(color: Color) ``` ### Parameters #### Path Parameters * None #### Query Parameters * None #### Request Body * None ### Parameters - **color** (`Color`) - SwiftUI color to apply to the blob. ### Gradient Configuration - Converts SwiftUI `Color` to system color (`NSColor` on macOS, `UIColor` on iOS). - Creates three-stop gradient: 1. Opaque color (position 0.0) 2. Opaque color (position 0.9) — maintain solid color through most of gradient 3. Transparent version of color (position 1.0) — fade to transparent at edges - Sets `colors` to the CGColor array. - Sets `locations` to `[0.0, 0.9, 1.0]`. ### Result Creates a soft-edged blob that transitions from solid color to transparent. ### Example ```swift let blob = BlobLayer(color: .red) blob.set(color: .blue) // Change to blue blob.set(color: .clear) // Transparent blob ``` ``` -------------------------------- ### Timer-Based Animation Scheduling Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/architecture.md Explains how independent timers trigger blob animations, utilizing CoreAnimation for rendering. ```plaintext Timer.publish(every: random(0.8/speed...1.2/speed), ...) ↓ Timer fires on main run loop ↓ BlobLayer.animate(speed:) called ↓ removeAllAnimations() clears previous ↓ Generate new random position & radius ↓ Create three CASpringAnimation instances ↓ (startPoint, endPoint, opacity) add() animations to layer ↓ CoreAnimation runs animations off-main-thread ↓ GPU renders updated blobs ``` -------------------------------- ### FluidGradient View Initializer Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/INDEX.md Defines the main structure for FluidGradient, a SwiftUI View. It allows customization of blobs, highlights, speed, and blur. ```swift public struct FluidGradient: View { public init(blobs: [Color], highlights: [Color] = [], speed: CGFloat = 1.0, blur: CGFloat = 0.75) } ``` -------------------------------- ### ResizableLayer Coder Initializer (Unsupported) Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/ResizableLayer.md This initializer is marked as unsupported to prevent the use of ResizableLayer in Interface Builder or storyboard-based initialization. It will cause a runtime crash if called. ```swift required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } ``` -------------------------------- ### ResizableLayer Method Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/INDEX.md Handles the auto-resizing of sublayers within ResizableLayer. ```APIDOC ## `ResizableLayer` Method ### Description Manages the layout and resizing of sublayers. ### Method #### `layoutSublayers()` ##### Description Automatically resizes sublayers to fit within the parent layer's bounds. ``` -------------------------------- ### BlobLayer Methods Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Methods for animating and configuring BlobLayer. Includes animation control, color setting, and generating new positions and radii. ```swift func animate(speed: CGFloat) func set(color: Color) func newPosition() -> CGPoint func newRadius() -> CGPoint ``` -------------------------------- ### Create a Gradient with Slow Animation Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Configure a gradient with a slower animation speed. Adjust the 'speed' parameter to a value less than 1.0. ```swift FluidGradient( blobs: [.red, .blue], speed: 0.5 // Half speed ) ``` -------------------------------- ### Blur Value State Flow Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/architecture.md Illustrates the data flow for blurValue changes, from FluidGradient's state to the Coordinator and View updates. ```plaintext FluidGradient @State blurValue ↓ (Binding passed to Coordinator) Coordinator.blurValue (Binding) ↓ (delegate called by FluidGradientView) FluidGradientView.delegate.updateBlur() ↓ (updates binding) Coordinator.blurValue.wrappedValue = newValue ↓ (triggers SwiftUI state update) FluidGradient body re-evaluated ↓ (blur filter applied with new value) .blur(radius: pow(blurValue, blur)) ``` -------------------------------- ### ResizableLayer Default Initializer Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/ResizableLayer.md Initializes a ResizableLayer. On macOS, it sets an autoresizing mask for automatic parent resizing. The sublayers array is initialized as empty. ```swift override init() ``` -------------------------------- ### FluidGradient Source File Organization Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/architecture.md This lists the main source files within the FluidGradient library and their primary responsibilities. It helps understand the module organization. ```plaintext Sources/FluidGradient/ ├── FluidGradient.swift (Main SwiftUI View + Representable + Coordinator) ├── FluidGradientView.swift (Native system view, layer management, animation scheduling) ├── BlobLayer.swift (CAGradientLayer subclass, blob animation logic) ├── ResizableLayer.swift (CALayer subclass, automatic sublayer resizing) └── CGPoint+Extensions.swift (Coordinate transformation utilities) ``` -------------------------------- ### FluidGradientDelegate Protocol Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/FluidGradientView.md Defines the delegate protocol for receiving blur update callbacks. ```APIDOC ## `FluidGradientDelegate` Protocol ### Description The view's delegate receives blur update callbacks. Implementation: calls `updateBlur()` which passes `min(frame.width, frame.height)` to the delegate. ### Methods #### `updateBlur(_ value: CGFloat)` - **value** (CGFloat) - The calculated blur value. ### Signature `func updateBlur(_ value: CGFloat)` ``` -------------------------------- ### BlobLayer Required Initializer Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/BlobLayer.md The required initializer for CoreAnimation when copying layers. ```APIDOC ## BlobLayer Required Initializer ### Description Required by CoreAnimation framework for layer copying. ### Signature ```swift public override init(layer: Any) ``` ### Parameters #### Parameters - **layer** (Any) - Required - The layer to copy from. ### Behavior Calls the superclass initializer `super.init(layer: layer)`. ``` -------------------------------- ### BlobLayer Initializer Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/BlobLayer.md Initializes a BlobLayer with a specified SwiftUI color. This sets up the layer as a radial gradient with random initial position, radius, and color configuration. ```APIDOC ## BlobLayer Initializer ### Description Initializes a BlobLayer with a specified SwiftUI color. This sets up the layer as a radial gradient with random initial position, radius, and color configuration. ### Signature ```swift init(color: Color) ``` ### Parameters #### Parameters - **color** (Color) - Required - The SwiftUI color for this blob's gradient. ### Initialization Behavior - Sets gradient type to `.radial` for blob-like appearance - On macOS: Sets autoresizing mask to `[.layerWidthSizable, .layerHeightSizable]` - Calls `set(color:)` to configure gradient colors and locations - Generates a random initial position via `newPosition()` - Generates a random initial radius via `newRadius()` - Sets `startPoint` to the random position - Sets `endPoint` to position displaced by radius (creates radial gradient from center outward) ### Initial State Example ```swift let blob = BlobLayer(color: .red) // blob.startPoint: random point in [0,1] normalized space, capped to [0,1] // blob.endPoint: startPoint + random offset, creating radial gradient // blob.colors: red → red → transparent ``` ``` -------------------------------- ### Layer Hierarchy Visualization Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Illustrates the hierarchical structure of layers within the FluidGradient view, showing the relationship between the main view, representable, native view, and the base and highlight layers with their blob sublayers. ```plaintext FluidGradient └─ Representable └─ FluidGradientView ├─ baseLayer (ResizableLayer) │ ├─ BlobLayer (CAGradientLayer) │ ├─ BlobLayer │ └─ ... └─ highlightLayer (ResizableLayer) ├─ BlobLayer ├─ BlobLayer └─ ... ``` -------------------------------- ### Thread-Safe Configuration Updates Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/configuration.md Perform all configuration updates for FluidGradient on the main thread to ensure thread safety. This is crucial for dynamic changes to speed or colors during runtime. ```swift DispatchQueue.main.async { view.update(speed: newSpeed) view.create(newColors, layer: view.baseLayer) } ``` -------------------------------- ### FluidGradient Coordinator Class Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/types.md Manages the FluidGradientView and synchronizes state between SwiftUI and the native view. It implements the FluidGradientDelegate protocol. ```swift class Coordinator: FluidGradientDelegate { var blobs: [Color] var highlights: [Color] var speed: CGFloat var blurValue: Binding var view: FluidGradientView } ``` -------------------------------- ### BlobLayer newPosition() Method Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/CGPoint+Extensions.md Illustrates the use of `capped()` within the `newPosition()` method of BlobLayer to generate a safe, normalized position. ```swift // BlobLayer.newPosition() uses capped() func newPosition() -> CGPoint { return CGPoint(x: CGFloat.random(in: 0.0...1.0), y: CGFloat.random(in: 0.0...1.0)).capped() } ``` -------------------------------- ### ResizableLayer Copy Initializer Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/ResizableLayer.md Required by CoreAnimation for layer copying during animations or property updates. This initializer is essential for the CoreAnimation framework's internal operations. ```swift public override init(layer: Any) { super.init(layer: layer) } ``` -------------------------------- ### BlobLayer Initializer Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/BlobLayer.md Initializes a BlobLayer with a specified SwiftUI color. This sets up the blob's gradient type, initial position, radius, and colors. ```swift let blob = BlobLayer(color: .red) ``` -------------------------------- ### Configure Blobs and Highlights Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/configuration.md Update the base layer blob colors and highlight colors after the FluidGradientView has been initialized. You can also update the animation speed in conjunction with these changes. ```swift let view = FluidGradientView(blobs: [.red], highlights: []) // Add more colors to base layer view.create([.red, .green, .blue], layer: view.baseLayer) // Add highlights view.create([.yellow, .orange], layer: view.highlightLayer) // Update animation view.update(speed: 1.5) ``` -------------------------------- ### iOS Lifecycle Method for FluidGradientView Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/FluidGradientView.md Use `layoutSubviews` to ensure sublayers are resized and blur is recalculated when the view's layout changes on iOS. ```swift public override func layoutSubviews() ``` -------------------------------- ### Create Blob Layers for FluidGradientView Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/FluidGradientView.md Use the `create` method to generate or update blob layers with specified colors. This method manages the addition, removal, and color updates of `BlobLayer` instances within a target CALayer. ```swift public func create(_ colors: [Color], layer: CALayer) ``` ```swift let view = FluidGradientView(blobs: [], highlights: []) view.create([.red, .green, .blue], layer: view.baseLayer) view.create([.yellow, .orange], layer: view.highlightLayer) ``` -------------------------------- ### Check Layer Structure Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Prints the sublayers of the main view's layer, and the count of sublayers for the base and highlight layers. Useful for debugging the layer hierarchy. ```swift print(view.layer.sublayers) print(view.baseLayer.sublayers?.count) print(view.highlightLayer.sublayers?.count) ``` -------------------------------- ### BlobLayer Methods Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Methods for animating and managing individual blob layers within the gradient. ```APIDOC ## BlobLayer Methods ### animate #### Description Animates the blob layer with a specified speed. #### Parameters - **speed** (CGFloat) - Required - The speed at which to animate the blob. ``` ```APIDOC ## BlobLayer Methods ### set #### Description Sets the color of the blob layer. #### Parameters - **color** (Color) - Required - The new color for the blob. ``` ```APIDOC ## BlobLayer Methods ### newPosition #### Description Calculates and returns a new position for the blob. #### Returns - (CGPoint) - The new position of the blob. ``` ```APIDOC ## BlobLayer Methods ### newRadius #### Description Calculates and returns a new radius for the blob. #### Returns - (CGPoint) - The new radius of the blob. ``` -------------------------------- ### animate(speed:) Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/BlobLayer.md Animates the blob to a random position, size, and opacity with adjustable speed. This method removes existing animations and applies new CASpringAnimations scaled by the provided speed. ```APIDOC ## animate(speed:) ### Description Animates the blob to a random position, size, and opacity. The animation speed is controlled by the `speed` parameter, which scales the parameters of the underlying `CASpringAnimation` instances. ### Method Signature ```swift func animate(speed: CGFloat) ``` ### Parameters #### Path Parameters * None #### Query Parameters * None #### Request Body * None ### Parameters - **speed** (`CGFloat`) - Animation speed multiplier. Must be > 0. ### Animation Details - Removes all existing animations. - Creates three `CASpringAnimation` instances with parameters scaled by speed: - `mass = 10 / speed` - `damping = 50` - `duration = 1 / speed` - Animation properties set: - `isRemovedOnCompletion = false` - `fillMode = .forwards` (maintains final animated value) ### Animated Properties - **startPoint**: Current position to New random position - **endPoint**: Current endpoint to New position displaced by radius - **opacity**: Current opacity to Random value in [0.5, 1.0] ### Behavior - Generates new random position via `newPosition()` (capped to [0,1] unit space). - Generates new random radius via `newRadius()` (aspect ratio adjusted). - Gets current animation values from `self.presentation() ?? self` to ensure smooth transitions. - Uses animation copies (not shared instances) for each property. - All three animations run concurrently. ### Example ```swift let blob = BlobLayer(color: .blue) blob.animate(speed: 1.0) // Normal speed animation blob.animate(speed: 2.0) // Double speed, shorter duration ``` ``` -------------------------------- ### iOS FluidGradient Path Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/architecture.md Details the rendering path for FluidGradient on iOS, from the FluidGradient struct to the explicit frame setting in layoutSubviews. ```text FluidGradient ↓ Representable: UIViewRepresentable ↓ makeUIView() → FluidGradientView ↓ FluidGradientView.layer (implicit) ↓ layoutSubviews() explicitly sets frames ↓ Resizing handled by parent view ``` -------------------------------- ### CGPoint Extensions Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Extensions providing utility functions for CGPoint manipulation. ```APIDOC ## CGPoint Extensions ### displace #### Description Displaces the CGPoint by a given point. #### Parameters - **point** (CGPoint) - Optional - The point by which to displace. Defaults to (0.0, 0.0). #### Returns - (CGPoint) - The displaced CGPoint. ``` ```APIDOC ## CGPoint Extensions ### capped #### Description Clamps the CGPoint values within a certain range (details not specified in source). #### Returns - (CGPoint) - The capped CGPoint. ``` -------------------------------- ### BlobLayer Methods Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/INDEX.md Methods for triggering blob animations and changing blob colors in BlobLayer. ```APIDOC ## `BlobLayer` Methods ### Description Manages individual blob animations and color configurations. ### Methods #### `animate(speed:)` ##### Description Triggers the animation for a blob layer. ##### Parameters - **speed** (`CGFloat`) - The speed at which the blob should animate. #### `set(color:)` ##### Description Changes the color of the blob layer. ##### Parameters - **color** (`Color`) - The new color for the blob. ``` -------------------------------- ### CGPoint Displacement Extension Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Extends CGPoint to displace its coordinates by a given point. A default displacement of (0,0) is provided. ```swift func displace(by point: CGPoint = .init(x: 0.0, y: 0.0)) -> CGPoint ``` -------------------------------- ### ResizableLayer layoutSublayers() Implementation Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/ResizableLayer.md Automatically resizes all sublayers to match the container's frame. This method is called by CoreAnimation when the layer's bounds or frame change, ensuring child layers fill the available space. ```swift public override func layoutSublayers() { super.layoutSublayers() sublayers?.forEach { layer in layer.frame = self.frame } } ``` -------------------------------- ### capped() Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/api-reference/CGPoint+Extensions.md Clamps a point's coordinates to the unit square [0, 1] × [0, 1]. This ensures that blob positions remain within the normalized coordinate space, even if random positions exceed the bounds. ```APIDOC ## capped() ### Description Clamps a point's coordinates to the unit square [0, 1] × [0, 1]. ### Method func capped() -> CGPoint ### Parameters None. ### Returns A new `CGPoint` with both x and y clamped to range `[0, 1]`. ### Implementation ```swift CGPoint(x: max(min(x, 1), 0), y: max(min(y, 1), 0)) ``` ### Example ```swift let position = CGPoint(x: 1.5, y: -0.2) let capped = position.capped() // capped.x = 1.0, capped.y = 0.0 // Used in BlobLayer.newPosition(): let randomPos = CGPoint(x: CGFloat.random(in: 0.0...1.0), y: CGFloat.random(in: 0.0...1.0)) let safePos = randomPos.capped() // Ensures [0,1] bounds ``` ``` -------------------------------- ### Create a Gradient with a Very Soft Blur Source: https://github.com/cindori/fluidgradient/blob/main/_autodocs/quick-reference.md Apply a soft blur effect to the gradient by setting the 'blur' parameter to a higher value, such as 1.5. ```swift FluidGradient( blobs: [.red, .blue], blur: 1.5 // Extra soft ) ```