Blending colors dynamically with the mix modifier

Blending colors dynamically with the mix modifier

Learn to create custom colors, adjust blend amounts, and choose color spaces with SwiftUI in iOS 18 for precise control.

In this reference article, we are going to explore how to blend colors in an easy and flexible way, using the new mix(with:by:) modifier introduced with the redesign of SwiftUI's Color API for iOS 18 and macOS 15.

This feature requires iOS 18 and Xcode 16.

The mix(with:by:in:) modifier works as follows:

  1. It takes two parameters: the color to blend with and the blend amount.
  2. The blend amount is a value between 0 and 1, where 0 means 100% of the original color and 1 means 100% of the color to blend with.

Let's start with a simple example of blending two colors:

import SwiftUI

struct ColorBlendDemoView: View {
    var body: some View {
        Rectangle()
            .fill(Color.red.mix(with: .blue, by: 0.5))
            .frame(width: 100, height: 100)
    }
}

In this example, the rectangle is filled with a color that's a 50/50 blend of red and blue. This results in a purple shade, demonstrating how colors can be programmatically mixed in SwiftUI.

Customizing the color space

Color blending can produce different results depending on the color space used.

SwiftUI allows you to specify the color space for blending:

struct ColorSpaceComparisonView: View {
    var body: some View {
        VStack {
            Rectangle()
                .fill(Color.red.mix(with: .blue, by: 0.5, in: .perceptual))
                .frame(width: 100, height: 100)

            Rectangle()
                .fill(Color.red.mix(with: .blue, by: 0.5, in: .device))
                .frame(width: 100, height: 100)
        }
    }
}

The in: parameter allows you to specify the color space:

  • perceptual (default): Blends colors in a way that appears more natural to human perception.
  • device: Blends colors based on their raw RGB values, which can be more mathematically accurate but may look less smooth to the human eye.

Creating an interactive color blender

Let's create a view that allows users to interactively blend colors:

struct InteractiveColorMixerView: View {
    @State private var color1 = Color.red
    @State private var color2 = Color.blue
    @State private var blendAmount = 0.5
    @State private var colorSpace: Gradient.ColorSpace = .perceptual
    
    var body: some View {
        NavigationStack {
            Form {
                Section("Set Colors") {
                    ColorPicker("1° Color", selection: $color1)
                    ColorPicker("2° Color", selection: $color2)
                }
                Section {
                    Picker("Color Space", selection: $colorSpace) {
                        Text("Perceptual").tag(Gradient.ColorSpace.perceptual)
                        Text("Device").tag(Gradient.ColorSpace.device)
                    }
                } header: {
                    Text("Set ColorSpace")
                }
                
                Section {
                    HStack {
                        Text(String(format: "%.2f", blendAmount))
                        Slider(value: $blendAmount)
                    }
                } header: {
                    Text("Set the amount of blending")
                }
                
                Section("Result") {
                    HStack {
                        Circle()
                            .fill(color1)
                        Image(systemName: "plus.app.fill")
                            .imageScale(.large)
                            .foregroundStyle(.secondary)
                        Circle()
                            .fill(color2)
                        Image(systemName: "equal.square.fill")
                            .imageScale(.large)
                            .foregroundStyle(.secondary)
                        Circle()
                            .fill(color1.mix(with: color2, by: blendAmount, in: colorSpace))
                    }
                }
            }
            .navigationTitle(".mix modifier")
        }
    }
}

This interactive view allows users to:

  1. Select two colors using ColorPicker.
  2. Adjust the blend amount using a Slider.
  3. Choose between perceptual and device color spaces.
  4. See the resulting blended color in real-time.

The SwiftUI Color API provides a powerful tool for blending colors with the mix(with:by:in:) modifier. This modifier processes two colors and a blend amount, optionally considering the color space, and returns a new blended color. These results can then be easily used in various UI elements, enabling developers to create sophisticated color management systems in their applications.