SwiftUI 그래픽 드로잉 기초

2 분 소요

SwiftUI 2D 드로잉 기술

  • 내장된 도형
  • 그래디언트 드로잉
  • 커스텀 드로잉

SwiftUI 도형

Shape 프로토콜

  • 원(Circle)
  • 사각형(Rectangle)
  • 모서리가 둥근 사각형(RoundedRectangle)
  • 타원(Ellipse)
var body: some View {
    Rectangle()
}

디폴트: 도형은 속한 뷰에서 사용할 수 있는 모든 공간을 차지, 부모 뷰의 포그라운드 색상으로 채움

도형의 색상: fill() 수정자
도형의 크기: frame() 수정자

Circle()
    .fill(Color.red)
    .frame(width: 200, height: 200)

스크린샷 2022-06-08 오전 11 38 10

테두리 선 두께: stroke() 수정자
외각선 색상: foregroundColor() 수정자

Capsule()
    .stroke(lineWidth: 10)
    .foregroundColor(.blue)
    .frame(width: 200, height: 100) 

스크린샷 2022-06-08 오전 11 41 12

  • StrokeStyle 인스턴스
    • 대시 라인을 이용(점선)
        RoundedRectangle(cornerRadius: CGFloat(20))
            .stroke(style: StrokeStyle(lineWidth: CGFloat(8), dash: [CGFloat(10)]))
            .foregroundColor(.blue)
            .frame(width: 200, height: 100)
      

      스크린샷 2022-06-08 오전 11 47 08

    • dash 값과 간격 값 추가
        Ellipse()
            .stroke(style: StrokeStyle(lineWidth: 20, 
                    dash: [CGFloat(10), CGFloat(5), CGFloat(2)], 
                    dashPhase: CGFloat(10)))
            .foregroundColor(.blue)
            .frame(width: 250, height: 150)
      

      스크린샷 2022-06-08 오전 11 49 54


오버레이 사용하기

외곽선과 도형의 색을 동시에 채우기 위해
fill 수정자와 stroke 수정자는 같이 사용x -> 오버레이(overlay)

Ellipse()
    .fill(Color.red)
    .overlay(Ellipse()
        .stroke(Color.blue, lineWidth: 10))
    .frame(width: 250, height: 150)

스크린샷 2022-06-08 오전 11 54 53


커스텀 경로와 도형 그리기

도형: Shape 프로토콜을 따르는 구조체 객체
Shape 프로토콜: path() 함수 구현 (CGRect 사각형을 받고, Path 객체를 반환)
Path 인스턴스: 포인트 간의 좌표를 지정하고 그려질 선을 정의하여 2차원 도형을 제공

  • 직선, 3차 및 2차 베지어 곡선, 호, 타원, 사각형 사용가능
  • 뷰에 직접 그림 가능
      var body: some View {
          Path { path in
              path.move(to: CGPoint(x: 10, y: 0))
              path.addLine(to: CGPoint(x: 10, y: 350))
              path.addLine(to: CGPoint(x: 300, y: 300))
              path.closeSubpath()
          }
          .fill(Color.green)
      }
    

    스크린샷 2022-06-08 오후 12 24 41

    • move - 시작점의 좌표
    • addLine - 지정된 포인트까지 직선 추가
    • addLines - 지정된 끝점들의 배열 간에 직선 추가
    • addArc - 반지름과 각도 값을 기반으로 호 추가
    • addCurve - 주어진 끝점과 제어점을 사용하여 3차 베지어 곡선 추가
    • addQuadCurve - 주어진 끝점과 제어점을 사용하여 2차 베지어 곡선 추가
    • closeSubPath - 끝점과 시작점을 연결하여 경로를 닫음
  • 재사용 가능한 컴포넌트로 커스텀 도형 구현(일반적)
      struct MyShape: Shape {
          func path(in rect: CGRect) -> Path { // path() 함수 필수
              var path = Path()
                
              path.move(to: CGPoint(x: rect.minX, y: rect.minY))
              path.addQuadCurve(to: CGPoint(x: rect.minX, y: rect.maxY), 
                                control: CGPoint(x: rect.midX, y: rect.midY))
              path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
              path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
              path.closeSubpath()
              return path
          }
      }
    

    CGRect 값은 삼각형을 그리는 경계를 정의하는 사용
    삼각형 한쪽 면은 3차 곡선

    <메인뷰>

      MyShape()
          .fill(Color.red)
          .frame(width: 360, height: 350)
    

    스크린샷 2022-06-08 오후 12 30 55


그래디언트 그리기

그래디언트에 포함될 색상 배열과 그래디언트를 렌더링한 방식을 제어하는 값으로 초기화된 Gradient 객체

  • 방사형 그래디언트
      let colors = Gradient(colors: [Color.red, Color.yellow, Color.green, 
                            Color.blue, Color.purple])
            
      var body: some View {
                
          Circle()
              .fill(RadialGradient(gradient: colors, 
                                   center: .center, 
                                   startRadius: CGFloat(0), 
                                   endRadius: CGFloat(300)))
      }
    

    스크린샷 2022-06-08 오후 12 42 32

  • 원뿔형 그래디언트
      Circle()
          .fill(AngularGradient(gradient: colors, center: .center))
    

    스크린샷 2022-06-08 오후 12 44 03

  • 선형 그래디언트
      Rectangle()
          .fill(LinearGradient(gradient: colors, startPoint: .topLeading, endPoint: .bottomTrailing))
          .frame(width: 360, height: 350)
    

    스크린샷 2022-06-08 오후 12 45 23

  • 커스텀 도형 + 그래디언트
      MyShape()
          .fill(RadialGradient(gradient: colors, 
                                 center: .center, 
                            startRadius: CGFloat(0), 
                              endRadius: CGFloat(300)))
          .background(LinearGradient(gradient: Gradient(colors: 
                                     [Color.black, Color.white]), 
                             startPoint: .topLeading, 
                               endPoint: .bottomTrailing))
          .frame(width: 350, height: 350)
    

    스크린샷 2022-06-08 오후 12 48 46

카테고리:

업데이트: