Draw a ring, a dial or a progress track that sweeps through your colors: call proAngularGradient(). You get SwiftUI's AngularGradient, and your first color comes back at the end, so the ring has no seam where it meets itself.
Circle()
.strokeBorder(brand._400.triad.proAngularGradient(), lineWidth: 8)
.frame(width: 80, height: 80)triad gives three families spread evenly around the hue wheel, all at _400, and the ring runs through each of them and back to the brand.
A ring through your themes#
Any array of colors or families works. This ring runs through the three destinations, Lisbon, Kyoto and Reykjavík:
Circle()
.strokeBorder([Color.proOrange, Color.proPink, Color.proSky].proAngularGradient(), lineWidth: 8)
.frame(width: 80, height: 80)A dial from one color#
On one color, proAngularGradient makes the other colors with a recipe. .analogous sweeps from the hue 30° to one side, through your color, to the hue 30° to the other, at the same lightness:
Circle()
.strokeBorder(brand._400.proAngularGradient(.analogous), lineWidth: 6)
.frame(width: 80, height: 80)How it behaves#
The sweep starts at the trailing edge, 3 o'clock, and runs clockwise around center. To start it somewhere else, such as the top of a progress ring, rotate the view with .rotationEffect(.degrees(-90)).
Your first color is added again at the end unless the last color already matches it in both light and dark mode, so there's never a seam and never a doubled stop. Blending, easing and dark mode work as they do for proGradient(), and one color gives a solid ring.
API#
proAngularGradient is an extension on arrays of Color and ProTheme, and on Color and ProTheme themselves.
public extension Array where Element == Color {
func proAngularGradient(center: UnitPoint = .center,
blend: ProGradient.Blend = .vivid, easing: ProGradient.Easing = .smooth) -> AngularGradient
}
// The same function exists on Array where Element == ProTheme.
public extension Color {
func proAngularGradient(_ recipe: ProGradient.Recipe = .subtle, center: UnitPoint = .center,
blend: ProGradient.Blend = .vivid, easing: ProGradient.Easing = .smooth) -> AngularGradient
}
// The same function exists on ProTheme.| Parameter | Type | Default | What other values do |
|---|---|---|---|
center | UnitPoint | .center | Moves the point the colors sweep around. |
blend | ProGradient.Blend | .vivid | .direct goes straight through OKLab; .rainbow goes around the hue wheel the long way. |
easing | ProGradient.Easing | .smooth | Another preset or .timingCurve(_:_:_:_:) moves where the colors change. |
recipe | ProGradient.Recipe | .subtle | One-color version only: another recipe or your own. |
It returns SwiftUI's AngularGradient, so it works anywhere a shape style does, such as .fill, .stroke and .strokeBorder.
Sources#
- ColorTokensKit source: Array+ProGradient.swift and GradientStops.swift.
- Apple, AngularGradient.
See also
- .proRadialGradient() Draw glows and spotlights that fade from the center outward without going gray.
- .harmony(_:) Build the harmony someone picks at runtime, from a picker or a setting, in one call.
- Color theory Pair stops that always read, and pick secondary hues that match your brand, in both modes.
- Gradient theory Add depth with gradients that stay vivid, from a single color or a recipe, in both modes.