Custom Shapes in SwiftUI | Advanced Learning #5
Shape
구현 목표
- 특정 점에서 특정 점을 이어 새로운 형태의 도형(
Shape
)을 그리는 방법
구현 태스크
Shape
프로토콜의 path
함수를 통해 새로운 도형 그리기
- 특정 이미지를 특정 도형 모양으로 자르기:
clipShape
핵심 코드
struct Triangle: Shape {
func path(in rect: CGRect) -> Path {
Path { path in
path.move(to: CGPoint(x: rect.midX, y: rect.minY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.midX, y: rect.minY))
}
}
}
...
Image("Polar_Bear")
.resizable()
.scaledToFill()
.frame(width: 300, height: 100)
.clipShape(Trapezoid())
path.move
는 도형의 특정 점으로 이동
path.addLine
은 현재 위치에서 특정 위치(상대적 위치, Rect
의 x, y 포인트를 통해 파악)로 이동하는 선 추가
clipShape
를 통해 특정 Shape
모양에 이미지를 넣을 수 있음
소스 코드
import SwiftUI
struct Triangle: Shape {
func path(in rect: CGRect) -> Path {
Path { path in
path.move(to: CGPoint(x: rect.midX, y: rect.minY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.midX, y: rect.minY))
}
}
}
struct Diamond: Shape {
func path(in rect: CGRect) -> Path {
Path { path in
let horizontalOffset: CGFloat = rect.width * 0.2
path.move(to: CGPoint(x: rect.midX, y: rect.minY))
path.addLine(to: CGPoint(x: rect.maxX - horizontalOffset, y: rect.midY))
path.addLine(to: CGPoint(x: rect.midX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX + horizontalOffset, y: rect.midY))
path.addLine(to: CGPoint(x: rect.midX, y: rect.minY))
}
}
}
struct Trapezoid: Shape {
func path(in rect: CGRect) -> Path {
Path { path in
let horizontalOffset: CGFloat = rect.width * 0.2
path.move(to: CGPoint(x: rect.minX + horizontalOffset, y: rect.minY))
path.addLine(to: CGPoint(x: rect.maxX - horizontalOffset, y: rect.minY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX + horizontalOffset, y: rect.minY))
}
}
}
struct CustomShapesBootCamp: View {
var body: some View {
VStack {
Triangle()
.stroke(style: StrokeStyle(lineWidth: 3, lineCap: .round, dash: [10]))
.fill(LinearGradient(gradient: Gradient(colors: [.red, .blue]), startPoint: .leading, endPoint: .trailing))
.frame(width: 180, height: 160)
Image("Polar_Bear")
.resizable()
.scaledToFill()
.frame(width: 300, height: 100)
.clipShape(Trapezoid())
}
}
}