SwiftUI 6.0 (iOS 18_macOS 15) new ways to play Color

Insert image description here

Overview

WWDC 2024’s reinstalled and upgraded SwiftUI 6.0 makes the different platforms (iOS 18/macOS 15) look more beautiful and beautiful.

Insert image description here

The dream color mixing function has finally come true in WWDC 24!

In this blog post, you will learn:

  • Overview
  • 1. Dream come true: Hybrid Colors
  • 2. Mix more than two colors
  • Summary

Believe that mixing two colors in SwiftUI 6.0 will be easy and easy after this lesson.

So what are you waiting for? Let’s start the Color Big Scudes now!

Let’s go!!! 😉


The video lesson for this article is here, and you are welcome to enjoy it:

SwiftUI 6.0 New Play on Color Color


1. Dream come true: Hybrid Colors

Once and for all, we wanted a way to mix colors in SwiftUI. No, in this WWDC 24 Apple seems to have heard our bald farmer.

In SwiftUI 6.0, Apple finally added the mix approach to the Color structure to break the ice:

Insert image description here Insert image description here

The mix method signature is simple: We just need to pass in two colors that need to be blended, a percent blended (blending fraction), and a color space (color space).

It is worth noting that there are two options for color space parameters: Device and perceptual, which we should use by default (perceptual). Because in theory, the way you mix colors should be meaningful to the human eye and consistent across different device screens.

Mixing based on device color space (device) may produce different results, and these results may or may not be what we want. The best way to see actual effect differences is through the lab.

In the following code, we blended pink and blue together in a 50% blend:

let leftColor = Color.pink
let rightColor = Color.blue
let mix = 0.5

RoundedRectangle(cornerRadius: 16)
    .fill(leftColor.mix(with: rightColor, by: mix, in: .perceptual))
    .frame(width: 100, height: 100) 

The following figure shows the effect of running in Playground:

Insert image description here

Because colors can now be blended together, the blend is easily animated.

struct ContentView: View {

    @State var showMixing = false

    var body: some View {
        VStack(spacing: 100) {
            RoundedRectangle(cornerRadius: 15)
                .foregroundStyle(.red.mix(with: showMixing ? .black.opacity(0.88) : .red, by: 0.9, in: .perceptual))
                .frame(width: 200, height: 200)

            Toggle(isOn: $showMixing) {
                Text("Show blend animation")
            }
            .font(.largeTitle)
            .toggleStyle(.button)
        }
        .animation(.smooth(duration: 5.0, extraBounce: 0.1), value: showMixing)
    }
} 

In the code above, we use the mix method with the universal animation animation modifier to make the color gradient animation “live”:

With the ColorPicker Color Selector view, we can also enjoy mixing different colors:

struct ColorMix: View {
    @State private var leftColor = Color.blue
    @State private var rightColor = Color.pink
    @State private var mix = 0.5

    var body: some View {
        VStack {
            HStack(spacing: 8) {
                ColorPicker("Left", selection: leftColor)
                    .labelsHidden()
                ColorPicker("Right", selection:rightColor)
                    .labelsHidden()
            }

            HStack {
                VStack {
                    RoundedRectangle(cornerRadius: 16)
                        .fill(leftColor)
                        .frame(width: 100, height: 100)
                    Text("\((1 - mix), format: .percent.precision(.fractionLength(0...2)))")
                }

                VStack {
                    RoundedRectangle(cornerRadius: 16)
                        .fill(rightColor)
                        .frame(width: 100, height: 100)
                    Text("\(mix, format: .percent.precision(.fractionLength(0...2)))")
                }
            }

            RoundedRectangle(cornerRadius: 16)
                .fill(leftColor.mix(with: rightColor, by: mix, in: .perceptual))
                .frame(width: 100, height: 100)
                .animation(.bouncy, value: mix)

            Slider(value: $mix, in: 0...1)
        }
        .padding()
    }
} 

As shown in the above code: We use two ColorPicker views to let the user select the desired color, and display the mixed result of the color in the rounded rectangle at the bottom through the mix method. We also use SwiftUI animation to make the mix look silky and smooth.

Compile and see the run effect in the Xcode preview: Insert image description here

2. Mix more than two colors

From the parameters of the mix method, it seems that only two colors can be mixed. But we can mix colors as long as we “subtotal”:

struct ColorMix: View {
    @State private var leftColor = Color.blue
    @State private var rightColor = Color.pink
    @State private var midColor = Color.green
    @State private var mix = 0.5

    private var mixedColor: Color {
        let twoMix = leftColor.mix(with: rightColor, by: mix, in: .perceptual)
        return midColor.mix(with: twoMix, by: mix, in: .perceptual)
    }


    var body: some View {
        VStack {
            HStack(spacing: 8) {
                ColorPicker("Left", selection: leftColor)
                    .labelsHidden()
                ColorPicker("Right", selection:midColor)
                    .labelsHidden()
                ColorPicker("Right", selection: rightColor)
                    .labelsHidden()
            }

            HStack {
                VStack {
                    RoundedRectangle(cornerRadius: 16)
                        .fill(leftColor)
                        .frame(width: 100, height: 100)
                    Text("\((1 - mix), format: .percent.precision(.fractionLength(0...2)))")
                }

                VStack {
                    RoundedRectangle(cornerRadius: 16)
                        .fill(midColor)
                        .frame(width: 100, height: 100)
                    Text("\(mix, format: .percent.precision(.fractionLength(0...2)))")
                }

                VStack {
                    RoundedRectangle(cornerRadius: 16)
                        .fill(rightColor)
                        .frame(width: 100, height: 100)
                    Text("\(mix, format: .percent.precision(.fractionLength(0...2)))")
                }
            }

            RoundedRectangle(cornerRadius: 16)
                .fill(mixedColor)
                .frame(width: 100, height: 100)
                .animation(.bouncy, value: mixedColor)

            Slider(value:mix, in: 0...1)
        }

        .padding()
    }
} 

As shown in the above code, we use the mixedColor calculation attribute to mix the left and right colors and then the middle color:

private var mixedColor: Color {
    let twoMix = leftColor.mix(with: rightColor, by: mix, in: .perceptual)
    return midColor.mix(with: twoMix, by: mix, in: .perceptual)
} 

Compiling and running are visible:

Insert image description here

Now, it’s really easy to make any two colors “happy” with the new mix in SwiftUI 6.0! Boutique! 💯

Summary

In this blog post, we discussed the new mix method for color Color structure in SwiftUI 6.0 (iOS 18/macOS 15), which is no longer a “dream” for any color!

Thank you for watching and meeting again! 😎

From

let leftColor = Color.pink
let rightColor = Color.blue
let mix = 0.5

RoundedRectangle(cornerRadius: 16)
    .fill(leftColor.mix(with: rightColor, by: mix, in: .perceptual))
    .frame(width: 100, height: 100)