티스토리 뷰

Path를 사용해서 화면에 그림을 그리는 방법을 알아보자. openGL이나 window GDI를 사용하는 것과 비슷하다. 화면에서 시작점으로 이동하고 선을 그리고 채우는 등의 작업을 할 수 있다. 공식 사이트에 나와있는 육각형 그리기를 따라해보면서 어떻게 동작하는지 알아보자.

 

 

 

HexagonParameters

육각형을 그리기 위해 필요한 각 점들의 위치를 상대적으로 계산할 수 있는 구조체를 정의한다. 꼭지점을 그릴 때 필요한 vertex의 상대적인 위치값이지만 원리는 이 포스팅에서 중요한게 아니기 때문에 설명을 생략한다. points는 순서대로 육각형의 12시 방향 vertex부터 반시계방향으로 정의되어있다.

CGFloat이라는 자료형을 사용한다는 것만 유의하고 넘어가자.

struct HexagonParameter {
    struct Segment {
        let useWidth: (CGFloat, CGFloat, CGFloat)
        let xFactors: (CGFloat, CGFloat, CGFloat)
        let useHeight: (CGFloat, CGFloat, CGFloat)
        let yFactors: (CGFloat, CGFloat, CGFloat)
    }
    
    static let adjustment: CGFloat = 0.05
    
    static let points = [
        Segment(
            useWidth:  (1.00, 1.00, 1.00),
            xFactors:  (0.60, 0.40, 0.50),
            useHeight: (1.00, 1.00, 0.00),
            yFactors:  (0.05, 0.05, 0.00)
        ),
        Segment(
            useWidth:  (1.00, 1.00, 0.00),
            xFactors:  (0.05, 0.00, 0.00),
            useHeight: (1.00, 1.00, 1.00),
            yFactors:  (0.20 + adjustment, 0.30 + adjustment, 0.25 + adjustment)
        ),
        Segment(
            useWidth:  (1.00, 1.00, 0.00),
            xFactors:  (0.00, 0.05, 0.00),
            useHeight: (1.00, 1.00, 1.00),
            yFactors:  (0.70 - adjustment, 0.80 - adjustment, 0.75 - adjustment)
        ),
        Segment(
            useWidth:  (1.00, 1.00, 1.00),
            xFactors:  (0.40, 0.60, 0.50),
            useHeight: (1.00, 1.00, 1.00),
            yFactors:  (0.95, 0.95, 1.00)
        ),
        Segment(
            useWidth:  (1.00, 1.00, 1.00),
            xFactors:  (0.95, 1.00, 1.00),
            useHeight: (1.00, 1.00, 1.00),
            yFactors:  (0.80 - adjustment, 0.70 - adjustment, 0.75 - adjustment)
        ),
        Segment(
            useWidth:  (1.00, 1.00, 1.00),
            xFactors:  (1.00, 0.95, 1.00),
            useHeight: (1.00, 1.00, 1.00),
            yFactors:  (0.30 + adjustment, 0.20 + adjustment, 0.25 + adjustment)
        )
    ]
}

 

 

 

Drawing Hexagon

이제 이 값을 가지고 육각형을 그려보자. 먼저 Path를 정의하고 시작점으로 이동한다.

// path.move(to:)
let pathSize: CGSize = CGSize(width: 100, height: 100)

Path {path in
	let xScale: CGFloat = 0.85
	let width = pathSize.width * xScale
	let height = pathSize.height
	let xOffset = pathSize.width * (1.0 - xScale) / 2.0
            
	path.move(to: CGPoint(
		x: xOffset + width * 0.95, 
		y: height * (0.2 + HexagonParameter.adjustment))
	)
}

문법이 GeometryReader와 비슷한 것을 볼 수 있는데, Path도 closure로 초기화 할 수 있기 때문이다. HexagonParameter에서 12시 방향 점부터 반시계방향으로 육각형을 그리도록 정의했기 때문에 범위에서 좌상단으로 이동한다.

 

반시계방향으로 육각형을 그린다.

 

addLine으로 선을 먼저 그려보자. 현재 path가 위치한 지점부터 to 위치로 직선을 그릴 수 있다.

// path.addLine(to:)
HexagonParameter.points.forEach {point in
	path.addLine(to: .init(
		x: xOffset + width * point.useWidth.0 * point.xFactors.0, 
		y: height * point.useHeight.0 * point.yFactors.0)
	)
}

여기까지 그리고 캔버스를 실행해보면 찌그러진 육각형이 그리진 것을 볼 수 있다. 심지어 육각형이 아니라 칠각형이다. HexagonParameter에서 육각형의 모서리를 곡선으로 그리려고 정의했기 때문에 앞서 이동한 점과 육각형의 시작점이 달라서 칠각형이 그려진것이다.

 

모서리를 곡선으로 그리기 위해 꼭지점을 어긋나게 그리고있다.

 

AddQuadCurve로 곡선을 더 그려보자. addLine과 비슷하게 to 위치로 선을 그리지만 control 좌표를 필요로 한다. 현재 path의 위치, control, to 로 곡선을 그린다.

// path.addQuadCurve(to:, control:)
path.addQuadCurve(
	to: .init(
		x: xOffset + width * point.useWidth.1 * point.xFactors.1, 
		y: height * point.useHeight.1 * point.yFactors.1
	),
	control: .init(
		x: xOffset + width * point.useWidth.2 * point.xFactors.2, 
		y: height * point.useHeight.2 * point.yFactors.2
	)
)

path를 마무리하면 검은색의 부드러운 꼭지점을 가진 육각형을 볼 수 있다. path도 다른 view를 다룰 때랑 똑같이 옵션을 추가할 수 있다.

// .fill(LinearGradiant.init(gradiant:, startPoint:, endPoint))
.fill(LinearGradient.init(
	gradient: .init(colors: [Color.purple, Color.blue]),
	startPoint: .init(x: 0.5, y: 0.1),
	endPoint: .init(x: 0.5, y: 0.9)
))

그라데이션으로 내부 색상을 칠해보자. gradient에 CGColor 리스트를 넣고 startPoint, endPoint를 정의하면 그라데이션을 그릴 수 있다. startPoint/endPoint는 UnitPoint를 사용하기 때문에 중앙 상단부터 중앙 하단까지 그라데이션이 이루어지도록 그리려면 startPoint(x: 0.5, y: 0), endPoint(x: 0.5, y: 1.0)으로 정의하면 된다.

그리고 frame으로 적절히 크기와 정렬을 설정하면 완성할 수 있다.

 

 

 

결과

부드러운 꼭지점을 가진 육각형을 그렸다.

 

Path를 사용하는 방법에 대해 알아봤는데 Path의 기능만 특수하게 사용하는 어떤 view를 구성하는게 좀 애매해서 Tutorial 리스트에는 못쓸 것 같다. 앞으로 Tutorial 리스트를 채울 여러 view들을 만들 때 Path를 사용해서 좀 더 보기좋게 만들 수 있겠다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함