I am working on the developer tutorial.
Drawing and Animation
Drawing Paths and Shapes
https://developer.apple.com/tutorials/swiftui/drawing-paths-and-shapes
Section 2 Step 9
How do you change the shape of the hexagon?
For example, what do I change in the code to add a side, making it a heptagon?
Drawing and Animation
Drawing Paths and Shapes
https://developer.apple.com/tutorials/swiftui/drawing-paths-and-shapes
Section 2 Step 9
How do you change the shape of the hexagon?
For example, what do I change in the code to add a side, making it a heptagon?
Code Block struct BadgeBackground: View { var body: some View { GeometryReader { geometry in Path { path in var width: CGFloat = min(geometry.size.width, geometry.size.height) let height = width let xScale: CGFloat = 0.832 let xOffset = (width * (1.0 - xScale)) / 2.0 width *= xScale path.move( to: CGPoint( x: xOffset + width * 0.95, y: height * (0.20 + HexagonParameters.adjustment))) HexagonParameters.points.forEach { path.addLine( to: .init( x: xOffset + width * $0.useWidth.0 * $0.xFactors.0, y: height * $0.useHeight.0 * $0.yFactors.0 ) ) path.addQuadCurve( to: .init( x: xOffset + width * $0.useWidth.1 * $0.xFactors.1, y: height * $0.useHeight.1 * $0.yFactors.1 ), control: .init( x: xOffset + width * $0.useWidth.2 * $0.xFactors.2, y: height * $0.useHeight.2 * $0.yFactors.2 ) ) } }
To learn how to change the shape, you need to know how the shape is held in HexagonParameters.How do you change the shape of the hexagon?
Each Segment in points represents parameters for two things:
A line representing an edge
A curve connecting the current edge to the next edge
As the parameters for hexagon is pre-calculated, you may need to:For example, what do I change in the code to add a side, making it a heptagon?
Pre-calculate the parameters of heptagon by yourself
Let Swift calculate the parameters
Create new Swift file PolygonParameters.swift:
Code Block import SwiftUI struct PolygonParameters { static let numberOfEdges = 7 static let curveFactor: CGFloat = 0.2 struct Segment { let useWidth: (CGFloat, CGFloat, CGFloat) let xFactors: (CGFloat, CGFloat, CGFloat) let useHeight: (CGFloat, CGFloat, CGFloat) let yFactors: (CGFloat, CGFloat, CGFloat) } static let angleOffset: CGFloat = -.pi / 2 // 90 degrees static func point(for angle: CGFloat) -> CGPoint { return CGPoint(x: cos(angle+angleOffset), y: sin(angle+angleOffset)) } static func point(from startAngle: CGFloat, to endAngle: CGFloat, factor: CGFloat) -> CGPoint { let start = point(for: startAngle) let end = point(for: endAngle) return CGPoint(x: start.x + (end.x-start.x)*factor, y: start.y + (end.y-start.y)*factor) } static let points = (0..<numberOfEdges).map {n->Segment in let prevAngle = (.pi*2/CGFloat(numberOfEdges)) * CGFloat(n-1) let currAngle = (.pi*2/CGFloat(numberOfEdges)) * CGFloat(n) let nextAngle = (.pi*2/CGFloat(numberOfEdges)) * CGFloat(n+1) let control = point(for: currAngle) let start = point(from: prevAngle, to: currAngle, factor: 1-curveFactor) let end = point(from: currAngle, to: nextAngle, factor: curveFactor) let r: CGFloat = 0.5 return Segment( useWidth: (1.00, 1.00, 1.00), xFactors: (r*start.x+0.5, r*end.x+0.5, r*control.x+0.5), useHeight: (1.00, 1.00, 1.00), yFactors: (r*start.y+0.5, r*end.y+0.5, r*control.y+0.5) ) } }
And use it as follows:
Code Block import SwiftUI struct Badge: View { var body: some View { GeometryReader { geometry in Path { path in var width: CGFloat = min(geometry.size.width, geometry.size.height) let height = width let xScale: CGFloat = 0.832 let xOffset = (width * (1.0 - xScale)) / 2.0 width *= xScale let last = PolygonParameters.points.last! path.move( to: CGPoint( x: xOffset + width * last.useWidth.2 * last.xFactors.2, y: height * last.useHeight.2 * last.yFactors.2 ) ) PolygonParameters.points.forEach { path.addLine( to: .init( x: xOffset + width * $0.useWidth.0 * $0.xFactors.0, y: height * $0.useHeight.0 * $0.yFactors.0 ) ) path.addQuadCurve( to: .init( x: xOffset + width * $0.useWidth.1 * $0.xFactors.1, y: height * $0.useHeight.1 * $0.yFactors.1 ), control: .init( x: xOffset + width * $0.useWidth.2 * $0.xFactors.2, y: height * $0.useHeight.2 * $0.yFactors.2 ) ) } } .fill(LinearGradient( gradient: .init(colors: [Self.gradientStart, Self.gradientEnd]), startPoint: .init(x: 0.5, y: 0), endPoint: .init(x: 0.5, y: 0.6) )) .aspectRatio(1, contentMode: .fit) } } static let gradientStart = Color(red: 239.0 / 255, green: 120.0 / 255, blue: 221.0 / 255) static let gradientEnd = Color(red: 239.0 / 255, green: 172.0 / 255, blue: 120.0 / 255) } struct Badge_Previews: PreviewProvider { static var previews: some View { Badge() } }
You can experiment what will be drawn with changing numberOfEdges, curveFactor and angleOffset of PolygonParameters.