Farbverläufe mit LinearGradient, RadialGradient und AngularGradient in SwiftUI


Softwareprodukte sind einer Mode unterworfen, einem Designparadigma, dem viele Entwickler folgen. Bis vor wenigen Jahren war es Skeuomorphismus, der den Anspruch verfolgte, Objekte in der digitalen Welt realitätsnah aussehen zu lassen. Eine Notzbuch-App wollte den Eindruck von Papier vermitteln, ein digitales Adressbuch schmückte sich mit einem Ledereinband. Inzwischen verwenden Entwickler Flächen mit nur einer Farbe. Farbverläufe gehören überwiegend der Vergangenheit an. Das soll nicht bedeuten, dass SwifUI keine Farbverläufe erzeugen kann. Das Gegenteil ist der Fall. Im Framework gibt es mehrere Funktionen für diesen Zweck. Ein LinearGradient erzeugt einen zweidimensionalen Farbverlauf über eine Fläche, ein RadialGradient einen kreisförmigen Farbverlauf. Weniger oft zum Einsatz kommt der AngularGradient. Er erzeugt Farbverläufe in einem Winkel.
Ein LinearGradient ist leicht zu definieren. In der einfachsten Variante besteht er aus einem Gradient, sowie einem Startpunkt und einem Endpunkt. Der Gradient wiederum benötigt als Parameter ein Array von Farben. Bei einem Farbverlauf mindestens zwei. Mehr Daten müssen nicht angegeben werden. Das System erledigt automatisch die Farbverteilung.

 LinearGradient(

     gradient: .init(colors: [.red, .blue]),

     startPoint: .leading,

     endPoint: .trailing

)

Soll ein Farbverlauf an mehreren Stellen im Programmcode verwendet werden, ist es zweckmäßig, die Erzeugung des Gradient in einer Methode auszulagern.

struct LinearGradientViewView {

    var body: some View {

        

        VStack {

            Text("Hello SwiftUI")

                .font(.title)

                .padding(.all, 20)

                .foregroundColor(.white)

                .background(self.createSimpleLinearGradient())

                .padding(.all, 10)

            

            Spacer()

        }

    }

    

    func createSimpleLinearGradient() -> LinearGradient {

        LinearGradient(

            gradient: .init(colors: [.red, .blue]),

            startPoint: .leading,

            endPoint: .trailing

        )

    }

}

Stacks Image 127

Die Anzahl der Farben ist nicht auf zwei begrenzt. Es können beliebig viele Farben sein. Ohne Konfiguration wird SwiftUI die Farben zwischen den zwei Punkten gleichmäßig verteilen. Mehr Kontrolle erlangt man, indem der Gradient nicht nur aus Farben, sondern aus sogenannten Gradientstopps definiert wird. Diese bestimmen zusätzlich zu der Farbe die Position, wo diese Farbe im Verlauf angeordnet werden soll. Es handelt sich dabei um eine relative Position mit Werten zwischen 0 und 1. 0 bezeichnet die Position am Anfang des Verlaufes, 1 an dessen Ende. 0.5 ist genau in der Mitte des Farbverlaufes.

func createComplexLinearGradient() -> LinearGradient {

        

    let gradient = Gradient(stops: [.init(color: .red, location: 0)

                                    , .init(color: .orange, location: 0.1)

                                    , .init(color: .yellow, location: 0.5)

                                    , .init(color: .green, location: 0.9)

                                    , .init(color: .blue, location: 1.0)])

        

    return LinearGradient(

        gradient: gradient,

        startPoint: .top,

        endPoint: .bottom

    )

}

Stacks Image 115

Einen Text mit einem Farbverlauf zu färben erfordert etwas mehr Aufwand. Am einfachsten ist es, die Struktur View um eine neue Methode zu erweitern, die dann mit einem Overlay und einer Maske arbeitet. Ein passender Name für eine solche Methode wäre gradientForeground.

extension View {

    public func gradientForeground<Overlay: View>(_ overlay: Overlay) -> some View {

        self.overlay(overlay).mask(self)

    }

}

Stacks Image 117

Ein RadialGradient funktioniert ähnlich einem LinearGradient, nur das es sich hierbei um einen kreisförmigen Farbverlauf handelt. Ein RadialGradient kann ebenfalls aus einem Array von Farben erzeugt werden, oder aus einem Array von GradientStops. Zusätzlich wird der Mittelpunkt des Farbverlaufes benötigt, oft im Zentrum des zu färbenden Objekts, sowie ein startRadius und ein endRadius.

func createSimpleRadialGradient() -> RadialGradient {

    let colors = Gradient(colors: [.red, .orange, .yellow, .green, .blue])

    return RadialGradient(gradient: colors, center: .center, startRadius: 0, endRadius: 100)

}

        

func createComplexRadialGradient() -> RadialGradient {

        

    let gradient = Gradient(stops: [.init(color: .red, location: 0)

                                    , .init(color: .orange, location: 0.7)

                                    , .init(color: .yellow, location: 0.8)

                                    , .init(color: .green, location: 0.9)

                                    , .init(color: .blue, location: 1.0)])

        

    return RadialGradient(

        gradient: gradient,

        center: .center,

        startRadius: 70,

        endRadius: 95

    )

}

Stacks Image 119
Stacks Image 121

Die dritte Art von Farbverlauf ist der RadialGradient. Er erzeugt Farbverläufe in einem Winkel. In der einfachsten Variante benötigt er ein Array von Farben und einen Mittelpunkt. Komplizierte Verläufe sind mit einer Auflistung von Gradientstopps möglich. Zusätzlich können ein Startwinkel und ein Endwinkel angegeben werden, über den sich der Farbverlauf erstreckt.

func createSimpleAngularGradient() -> AngularGradient {

    let colors = Gradient(colors: [.red, .orange, .yellow, .green, .blue])

    return AngularGradient(gradient: colors, center: .center)

}

    

func createComplexAngularGradient() -> AngularGradient {

        

    let gradient = Gradient(stops: [.init(color: .red, location: 0)

                                    , .init(color: .orange, location: 0.1)

                                    , .init(color: .yellow, location: 0.5)

                                    , .init(color: .green, location: 0.9)

                                    , .init(color: .blue, location: 1.0)])

        

    return AngularGradient(gradient: gradient, center: .topTrailing, startAngle: .degrees(90), endAngle: .degrees(180))

}

Stacks Image 123

Geschrieben am: 26.07.2020
Technologien: Swift, SwiftUI, macOS, iOS