UIBezierPath 사용해보기

2020. 10. 16. 17:07iOS/Swift

정말 오랜만에 포스팅을 해보려 합니다 😭

오늘은 UIBezierPath를 사용해 보려고 하는데요 ~!! 어떻게 사용하는지 차근차근 실습해 보면서 알아 보겠습니다.

정말 항상 감사드리는 Zedd 님의 포스팅을 참고해 가며 하나씩 알아볼께요

zeddios.tistory.com/814

 

iOS ) UIBezierPath (1)

안녕하세요 :) Zedd입니다. UIBezierPath를 써야 할 일이 생겨서 ㅎㅎㅎㅎ UIBezierPath를 공부해보려고 해요. 일단 베지어 이 친구를 알아야 할 것 같은데요 https://blog.coderifleman.com/2016/12/30/bezier-cu..

zeddios.tistory.com

공식 문서에서는 다음과 같이 소개하고 있습니다.

'A path that consists of straight and curved line segments that you can render in your custom views.'

번역하자면 '사용자 정의 뷰에서 렌더링할 수 있는 직선 및 곡선 선 세그먼트로 구성된 경로입니다.' ..?

번역기 돌려서 살짝 어색하긴 하지만 느낌만 알자면 Custom View에서 렌더링할 수 있는 직선, 곡선, 선 세그먼트로 구성된 경로 라고 생각해 보면 될 것 같아요 ~~!! 제가 이 베지어패쓰를 공부해 보고 싶던 이유도 뷰 안에서 컴포넌트들로 만들기 힘든 부분들을 해결할 수 있다고 생각해서 그려보려 합니다.

다음의 공식 문서에서는 BezierPath 의 사용 방법에 대해 한단계 씩 자세히 설명해 주었습니다.

developer.apple.com/library/archive/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/BezierPaths/BezierPaths.html

 

Drawing Shapes Using Bézier Paths

Drawing Shapes Using Bézier Paths In iOS 3.2 and later, you can use the UIBezierPath class to create vector-based paths. The UIBezierPath class is an Objective-C wrapper for the path-related features in the Core Graphics framework. You can use this class

developer.apple.com

먼저 1. Create the path object, path 객체를 만들어야 합니다.

Bezier Path의 생성자에는 위에 여러가지가 있지만, 오늘은 우선적으로 기본 생성자를 통해 empty path object를 활용해 보겠습니다.

let path = UIBezierPath()

 

그 다음 2. Set any relevant drawing attributes of your UIBezierPath object, such as the lineWidth or lineJoinStyle properties for stroked paths or the usesEvenOddFillRule property for filled paths. These drawing attributes apply to the entire path.

음 ...🤔 뭔가 많지만 대충 보자면 생성한 path 객체의 속성들을 설정해 주라는 소리 같습니다. (lineWidth, lineJoinStyle, usesEvenOddFillRull 등과 같은)

path.lineWidth = 10
path.lineJoinStyle = .round

저는 여기서 두가지만 설정해 보겠습니다. 문서에서 설명한 속성 중 usesEvenOddFillRull은 사실 잘이해가 안가서 천천히 나중에 알아보도록 하구

lineWidth의 경우 말그대로 선의 굵기와 같은 부분이고 

lineJoinStyle은 문서를 보니 The shape of the joints between connected segments of a stroked path., 스트로크 패스간의 연결 부분의 모양을 결정해 주는 속성 같네요 ~~!!

다음 3. Set the starting point of the initial segment using the moveToPoint: method.

move(to:) 초기 선의 시작점을 설정해야 합니다.

path.move(to: CGPoint(x: 100, y: 100))

4. Add line and curve segments to define a subpath.

선과 곡성 세그먼트를 추가하여 subpath를 정의합니다. 말은 조금 어렵지만, 방법은 단순합니다. move 함수를 통해 설정한 시작점으로 부터 도착 지점의 좌표를 지정하여 두 좌표를 잇는 선분을 그리 겠다는 뜻입니다.

path.addLine(to: CGPoint(x: 100, y: 200))

path의 메소드 addLine(to:) 함수를 호출하여 도착 지점을 y + 100 인 위치로 지정한 위치로 설정하였습니다.

마지막으로 5. Optionally, close the subpath by calling closePath, which draws a straight line segment from the end of the last segment to the beginning of the first.

선택적으로 close path를 호출함으로서 subath를 닫는다. close 는 마지막 세그먼트의 끝에서 시작 세그먼트의 시작 지점을 그린다.

path를 통해 선들을 여러개 그었을 때 최종적으로 도착한 위치와 첫 시작점 의 위치를 잇는 선을 close() 메소드를 통해 수행하게 됩니다.

path.close()

이제 Optionally, repeat the steps 3, 4, and 5 to define additional subpaths. 선택적으로 3,4,5 단계를 계속해서 거쳐 나가며 선들을 그려 나갈 수 있게 됩니다.

앞서 말씀 드렸 듯 이 BezierPath는 커스텀 뷰 위에서 여러가지 선들을 렌더링 할 수 있습니다. 따라서 새로운 커스텀 뷰를 만들어 주고 그 위 draw 함수에서 작성해 보겠습니다.

커스텀 뷰를 작성한 다음,

class BezierPathView: UIView {
    
    
    override func draw(_ rect: CGRect) {
        
        let path = UIBezierPath()
        
        path.lineWidth = 10
        path.lineJoinStyle = .round
        
        path.move(to: CGPoint(x: 100, y: 100))
        path.addLine(to: CGPoint(x: 100, y: 200))
        path.close()
    }
}

기본 뷰컨트롤러 위에 넣어주도록 하겠습니다.

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let view = BezierPathView(frame: self.view.frame)
        view.backgroundColor = .clear
        self.view.addSubview(view)
        
        // Do any additional setup after loading the view.
    }
}

하지만, 여기서 끝이 아닙니다. !! 실제로 위 코드를 실행 해 보셔도 아무런 그림이 나타나지 않게 됩니다.

이유는 UIBezierPath의 Overview 안에서 확인 해 볼 수 있었는데요 ~!!

After configuring the geometry and attributes of a Bézier path, you draw the path in the current graphics context using the stroke() and fill() methods.

번역기와 여러 자료들을 참고 했을 때 BezierPath의 경로를 앞서 여러가지 메소드를 통해 정의해 주었습니다. 그러나 이 경로는 실체가 없다고 볼 수 있는데요 ~!! 이 경로를 바탕으로 stroke()와 fill()메소드를 통해 그래픽 을 그려주게 됩니다.

stroke 메소드의 경우 path로 연결된 경로를 선으로서 이어주는 역할을 합니다.

fill 메소드는 path로 둘러싸여진 영역을 채워주는 역할을 합니다.

다시 이제 그려주기 위해 커스텀 뷰의 드로우 메소드를 바꿔주도록 하겠습니다.

class BezierPathView: UIView {
    
    override func draw(_ rect: CGRect) {
        
        let path = UIBezierPath()
        
        path.lineWidth = 10
        path.lineJoinStyle = .round
        
        path.move(to: CGPoint(x: 100, y: 100))
        path.addLine(to: CGPoint(x: 100, y: 200))
//        path.close()
        
        path.stroke()
    }
}

close 메소드는 현재 경로가 두개뿐이기 때문에 의미가 없으므로 지워주고 stroke를 통해 경로를 직접 그려 보겠습니다. 이제 실행시켜 보면

직선이 잘 그려 졌다.

한번 점을 하 나 더 그려볼까요 ~~!

class BezierPathView: UIView {
    
    override func draw(_ rect: CGRect) {
        
        let path = UIBezierPath()
        
        path.lineWidth = 10
        path.lineJoinStyle = .round
        
        path.move(to: CGPoint(x: 100, y: 100))
        path.addLine(to: CGPoint(x: 100, y: 200))
        path.addLine(to: CGPoint(x: 300, y: 100)) // 추가된 부분
        
        path.stroke()
    }
}

직선이 두 개 생성 되고 삼각형과 비슷한 화면이 만들어 졌습니다. ! 이제 close를 다시 호출해 주어 진짜 삼각형을 한번 만들어보겠습니다.

class BezierPathView: UIView {
    
    override func draw(_ rect: CGRect) {
        
        let path = UIBezierPath()
        
        path.lineWidth = 10
        path.lineJoinStyle = .round
        
        path.move(to: CGPoint(x: 100, y: 100))
        path.addLine(to: CGPoint(x: 100, y: 200))
        path.addLine(to: CGPoint(x: 300, y: 100))
        path.close()
        
        path.stroke()
        
    }
}

타다 ~~!

삼각형은 만들어 보았습니다. 이제 면을 한번 채워볼까요 ~!!

앞서 봤던 fill 메소드를 호출해 보겠습니다.

class BezierPathView: UIView {
    
    override func draw(_ rect: CGRect) {
        
        let path = UIBezierPath()
        
        path.lineWidth = 10
        path.lineJoinStyle = .round
        
        path.move(to: CGPoint(x: 100, y: 100))
        path.addLine(to: CGPoint(x: 100, y: 200))
        path.addLine(to: CGPoint(x: 300, y: 100))
        path.close()
        
        UIColor.systemYellow.set() // 색상 변경
        path.fill()
        
        UIColor.black.set() // 색상 변경
        path.stroke()
        
    }
}

타다 ~~~

이쁜 삼각형 한번 만들어 봤습니다.

BezierPath에는 선의 굵기나 접점 부분말고도 다양한 속성들을 설정할 수 있으니 문서 보면서 하나씩 바꿔보면 재밌을 것 같아요 ~~

'iOS > Swift' 카테고리의 다른 글

Swift Combine은 또 뭐야 ..?  (1) 2020.09.04
KVO에 대해 알아보고 적용해 보자 !!  (0) 2020.08.07
Swift Lint 사용해보기 !!  (2) 2020.04.10