I have a custom Shape in SwiftUI that is a series of CGPoints that form different lines.
I want to be able to draw a border around each individual path and right now the only thing I can think of is creating another Shape that takes the original CGPoints and adds x,y padding to each point but I wanted to see if there was another way that perhaps is built-in that I couldn't find.
For example, my shape is
-----
|
|
and I want to add a border Shape so I can detect when someone is in a bound where the # represents a new possible Shape around the original paths.
########
#----- #
######
#|#
#|#
#
Is there a way to implement this that is built in?
edit: code I'm currently thinking about to draw the border, very early but gives a gist of what I'm thinking
struct DrawShapeBorder: Shape {
var points: [CGPoint]
func path(in rect: CGRect) -> Path {
var path: Path = Path()
guard let startingPoint = points.first else {
return path
}
// go up
let upStartingPoint = CGPoint(x: startingPoint.x, y: startingPoint.y + 5)
path.move(to: upStartingPoint)
for pointLocation in points {
path.addLine(to: pointLocation)
}
return path
}
}
As @Evergreen suggested in the comments, you can use the stroke
modifier... but the tricky thing is that you can only apply one of these, so you can't do .stroke().stroke().stroke()
, unlike .shadow().shadow().shadow()
.
However, you can work around this by using a ZStack
containing 2 copies of the shape, then adding a different stroke to each of them.
struct ContentView: View {
var body: some View {
DrawShapeBorder(points: [
CGPoint(x: 100, y: 150),
CGPoint(x: 300, y: 100),
CGPoint(x: 300, y: 200),
CGPoint(x: 100, y: 200)
])
.stroked()
}
}
struct DrawShapeBorder: Shape {
/// add the double border
func stroked() -> some View {
ZStack {
self.stroke(Color.red, style: StrokeStyle(lineWidth: 20, lineCap: .round, lineJoin: .round))
self.stroke(Color.white, style: StrokeStyle(lineWidth: 10, lineCap: .round, lineJoin: .round))
}
}
var points: [CGPoint]
func path(in rect: CGRect) -> Path {
var path: Path = Path()
guard let startingPoint = points.first else {
return path
}
// go up
let upStartingPoint = CGPoint(x: startingPoint.x, y: startingPoint.y + 5)
path.move(to: upStartingPoint)
for pointLocation in points {
path.addLine(to: pointLocation)
}
return path
}
}
Result:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With