How to draw an outline around a shape that grows externally in SwiftUI?

88 Views Asked by At

Imagine this scenario:

  1. You obtained a custom shape path (for instance like this), but one of the default shapes will do as well.
  2. You want to draw the outline of that shape, with a lineWidth that depends on some @State variable
  3. The outline must grow externally so that even when it gets too big, it doesn't lose its contour's shape
  4. The inner fill is possibly transparent, for what matters.

So, I can't use strokeBorder<S>(_ content: S, lineWidth: CGFloat = 1) since its outline is centered on the actual contour of the path, as per documentation.

Also can't use stroke<S>(_ content: S, lineWidth: CGFloat = 1) (documentation here) since the effect is apparently just about the same, the outline is drawn centered.

An example code snippet reproducing the issue is the following:

struct ContentView: View {
    @State private var outlineSize: CGFloat = 1

    var body: some View {
        
        VStack {
            Circle()
                .stroke(.red, lineWidth: self.outlineSize)
                .frame(width: 100, height: 100)
            
            Slider(value: self.$outlineSize, in: 1...10)
        }
    }
}
1

There are 1 best solutions below

1
yawnobleix On

What about adding an overlay to the circle where the overlay contains the border?

struct ContentView: View {
    @State private var outlineSize: CGFloat = 1
    
    var body: some View {
        
        VStack {
            
            Circle()
                .fill(.white)
                .frame(width: 100, height: 100)
                .overlay(
                    Circle()
                        .stroke(.red, lineWidth: self.outlineSize)
                        .frame(width: 100 + outlineSize, height: 100 + outlineSize)
                    )
            
            Slider(value: self.$outlineSize, in: 1...10)
        }
    }
}

Another solution would be to adjust the frame of the circle, but this changes the behaviour slightly where the circle frame expands and affects other views.

struct ContentView: View {
    @State private var outlineSize: CGFloat = 1
    
    var body: some View {
        
        VStack {
            
            Circle()
                .stroke(.red, lineWidth: self.outlineSize)
                .frame(width: 100 + outlineSize, height: 100 + outlineSize)
            
            Slider(value: self.$outlineSize, in: 1...10)
        }
    }
}