seong_hye, the developer

SwiftUI) Path에 대해 알아보기 본문

IOS/SwiftUI

SwiftUI) Path에 대해 알아보기

seong_hye 2025. 7. 21.

 

📘 Path

벡터 그래픽 기반 2D 도형을 정의하는 구조체

직접 좌표를 찍고 연결해서 원하는 도형을 만들 수 있음


🔹 기본 정의

struct Path {
	var elements: [Path.Element]	// 선, 곡선, 이동 등으로 이루어진 요소
}

🔹 명령어

🔍 시작 / 닫기

함수 설명
move(to: CGPoint) 경로의 시작점을 지정 (펜을 들어서 새 좌표로 이동)
closeSubpath() 현재 경로를 닫음 (마지막 점 -> 시작점 자동 연결)

 

🔍 직선

함수 설명
addLine(to: CGPoint) 현재 위치에서 지정한 점까지 직선 추가
addLines(_ points: [CGPoint]) 현재 위치에서 여러 점들을 차례로 직선으로 연결
addRect(CGRect) 사각형 추가
addRects([CGRect]) 여러 사각형 추가
addRoundedRect(in rect: CGRect, cornerSize: CGSize, style: RoundedCornerStyle) 모서리가 둥근 사각형 추가

 

🔍 곡선

함수 설명
addQuadCurve(to:CGPoint, control: CGPoint) 현재 위치에서 to까지 하나의 제어점(control)을 사용하는 2차 베지어 곡선
addCurve(to:CGPoint, control1: CGPoint, control2:CGPoint) 현재 위치에서 to까지, 두 개의 제어점을 사용하는  3차 베지어 곡선
addArc(center: CGPoint, radius: CGFloat, startAngle: Angle, endAngle: Angle, clockwise: Bool) 원호(arc) 추가
addEllipse(in: CGRect) 타원 / 원 추가

 

🔍 도형 결합

함수 설명
addPath(Path, transform: CGAffineTransform = .identity) 다른 Path를 현재 Path에 추가

 

🔍 Geometry 관련

함수 설명
contains(CGPoint, eoFill: Bool = false) 특정 점이 Path 내부에 포함되는지 여부 검사
boundingRect Path의 외곽을 감싸는 최소 사각형

🔹 기본 사용법

➡️  기본 도형 그리기

struct PathExample: View {
	var body: some View {
    	Path {	path in
        	// 시작점 이동
        	path.move(to: CGPoint(x: 50, y: 50))
            // 직선 그리기
            path.addLine(to: CGPoint(x: 150, y: 50))
            path.addLine(to: CGPoint(x: 150, y: 150))
            path.addLine(to: CGPoint(x: 50, y: 150))
            // 도형 닫기
            path.closeSubpath()
        }
        .stroke(Color.blue, lineWidth: 3) // 선만 그리기
        .fill(COlor.green)	// 도형 채우기
    }
}



➡️  곡선 그리기

Path { path in
	path.move(to: CGPoint(x:50, y: 200))
    path.addQuadCurve(to: CGpoint(x: 250, y: 250), control: CGPoint(x: 150, y: 100))
}
.stroke(Color.red, lineWidth: 2)


🔹 추가 코드

@State private var points: [CGPoint] = []
@State private var isClosed = false

GeometryReader { geo in
	ZStack {
    	//Path 그리기
        Path { path in
        	guard !points.isEmpty else { return }
            path.move(to: points[0])
            for p in points.dropFirst() {
            	path.addLine(to: p)
            }
            if isClosed, points.count >= 3 {
            	path.closeSubpath()
            }	
        }
        .fill(isClosed ? Color.blue.opacity(0.18) : .clear)
        .stroke(isClosed ? Color.blue : Color.accentColor, lineWidth; 2)
        
        // 점 표시
        ForEach(points.indices, id: \.self) { i in
        	Circle()
            	.fill(i == 0 ? .orange : .blue)
                .position(points[i])
        }
        ...
        // 클릭 한 위치에 맞게 배열에 추가
        .gesture(
        	DragGesture(minimumDistance: 0)
            	.onEnded {value in
                	guard !isClosed else {return}
                    let p = value.location
                    if shouldClose(with: p) {
                    	withAnimation(.smooth) {
                        	isClosed = true
                        }
                    } else {
                    	withAnimation(.snappy) {
                        	points.append(p)
                        }
                    }
                }
                ..


🔹Path vs Shape

Path: 도형 그리는 "저수준" API

Shape 프로토콜: Path를 그려주는 구조체

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.closeSubpath()
        }
    }
}

🔹 Path의 활용

커스텀 도형 ( 삼각형, 다각형, 별, 파형 등)

애니메이션 (trim(from:to:)으로 경로 따라 그리기)

마스크(.clipShape(Path))로 특정 부분만 보여주기

차트/그래프 라인 직접 그리기


 

Comments