Exploring spatial borders with SwiftUI
September 26, 2024
Today's inspiration comes from a mix of the Flighty app and visionOS components. We will explore
We’ll explore what tools provided by SwiftUI can be used to achieve this effect, playing with gradients, unit points, and strokes.
Hit the road
Start with the basic layout. You can choose dimensions and overlaying content whatever you want, further in the article we will mostly focus on the capsule component.
One of the possible options of adding a border is overlaying another shape with the stroke applied on it.
To make things a bit more joyful, replace a solid color with a gradient as a fill component.
Here values for starting and ending points are taken to match the visionOS design a little bit. Anyway, let's discuss what they mean.
Units and colors
Instance of Gradient
type we pass as the first parameter defines how different colors we pass into are represented along the LinearGradient
.
You can try building gradients visually in Figma and play around with different combinations of stops and colors.
Unit points aren't much harder. Unit is a normalized value in range from 0.0 to 1.0. Normalized means that it represents a relative value, not an absolute one.
For example, we have a shape that is 300 width and 400 height. A unit point (x: 0.2, y: 0.4) within this shape has absolute coordinates (x: 0.2 * 300, y: 0.4 * 400), or (x: 60, y: 160). Yes, to get the absolute value of a unit point, you simply multiply the corresponding coordinates.
Thus, startPoint
represents the point where the linear gradient takes it's origin, endPoint
represents where it finishes. The image below shows the approximate location of the points.
To learn more about coordinate systems and their applications, read the Core Animation Programming Guide.
Moving further
If you look a little closer, you will see that the filling's width is not constant along the border. That's a drawback of having non-opaque colors in gradient and stroke together.
To fix it, we can apply strokeBorder
modifier.
As the last stroke, let's wrap this logic into a separate modifier, so in further it can be used with any shape and content.
With a thinner border, it looks even more elegant.
Where to go from here?
Imagination is perhaps the only limitation.
Thank you for reading! If you’re interested in iOS development, feel free to explore my other articles.
See you in the next experiments 🙌