본문 바로가기
iOS/SwiftUI

#13 Drawing & Custom Graphics

by HaningYa 2020. 10. 23.
728x90

더 복잡한 앱을 개발하기 시작하면 SwiftUI가 제공하는 기본 제공 컨트롤보다 더 많은 custom 을 위한 유연함이 필요하다.
SwiftUI는 앱 내에서 그래픽 생성을 지원하는 풍부한 라이브러리를 제공한다.

그래픽은 사용자에게 정보를 효율적이고 이해하기 쉽게 전달한다.
예를 들어, 동일한 정보를 그래픽으로 보는게 읽는 것 보다 시간이 덜 걸린다. 
이 장에서는 공항 앱을위한 몇 가지 awards 그래픽을 만들어 SwiftUI에서 그래픽을 사용해본다.

Creating shapes

starter project 에는 작은 공항을 위한 앱이 있다.
3개의 award 뱃지를 만들 것 이다.

뱃지를 그릴 FirstVisitAward.swift 파일을 만들고 AirportAwards.swift 에 FirstVisitAward를 scrollView 안에 넣어준다.

SwiftUI에서 기본 drawing structure은 Shape 가 있다. (simple primitive shape set)

먼저 사각형을 추가하기 위해 FirstVisitAward.swift 에서 기본 Text를 지우고 Rectagle() 로 바꾼다.

이 사격형은 SwiftUI 에서 도형을 그릴때 default 값이 무엇인지 보여주고 있다.
만약 명시적으로 fill 이나 strock 를 알려주지 않으면 shape 는 현재 foreground color 로 채워질 것이다. (Color.primary)
항상 다크모드에서도 어떻게 보여지는지 확인해야 한다.

            .environment(\.colorScheme, .dark)

Xcode 11.4 에서 enviroment 를 바꿔도 background 가 바뀌지 않는 버그가 있어서 preview 를 NavigationView 로 wrap 해서 확인한다.

NavigationView wrapping 해도 바탕 흰색인데..?

Rectangle()
                .fill(Color.blue)
                .frame(width: 200, height: 200)

 

defualt 를 override 해서 light 모드던 dark 모드던 같은 색을 띈다.
여기서 modifier 순서가 중요한데 fill은 frame 전에 위치해야 한다. 
border(_:width:)를 통해 외곽선을 만들 수 도 있다.

Using gradients

solid color 대신 gradient fill을 사용할 것 이다.

linear-gradient 색들 사이를 부드럽게 전환하며 보여준다. startPoint 와 endPoint 는 UnitPoint 구조체를 사용한다.
이 구조체는 값의 범위를 0 부터 1의 범위로 만들어 정확한 값 없이 범위를 쉽게 정의할 수 있게 해준다.

UnitPoints origin 좌표는 (0,0) 으로 상단왼쪽에 위치하고 오른쪽 아래로 갈수록 증가한다.
starting point 를 bottom left corner 로 정하고 endpoint 를 top right corner 로 지정했다.

linear-gradient 는 무조건 0부터 1까지의 범위로 강제하진 않는다. 시작점과 끝점을 원하는 아무데나 view 밖에서도 정의할 수 있다. 
*이 point들은 color의 끝이 아닌 transition의 끝을 뜻한다. Color는 이러한 지점을 지나서 end color까지 진행된다.

Rotating shapes

이번엔 만든 사각형을 회전시키며 새로운 사각형 2개를 만들어 본다.
ForEach 로 만든다.

  • 3개의 사각형을 담을 ZStack을 만든다. ZStack은 content를 배치가고 양 축에 정렬한다.
  • ForEach 를 통해 순회하며 (0, 1, 2) index 인 i 를 전달한다.
  • 사각형을 만드는 코드는 변함이 없지만 i*60 값으로 회전시킨다,

Adding Images

drawing 과 image를 합치는 건 공수를 줄여준다.

크기가 정해져 있는 사각형을 만드는 건 image를 다루는 것을 더 어렵게 만든다.
더 나은 옵션으로는 frame 을 채워서 모든 크기에 맞게 조정하는 것이다. 적응형 view를 만든다

frame modifier를 rectangle 에서 없애고 preview 에는 frame 을 적용해준다.

그리고 image에 resizeable modifier 를 적용하고 회전과 opacity 를 준다.

Scaling drawings in views

실행해보면 뱃지가 타이블과 겹치는 문제가 있다.

회전된 shape 가 사각형 내에 위치하도록 사이즈를 조정해야 한다.

  • GeometryReader container는 내부 view 의 size 와 shape 를 가져올 수 있게 하여 constants에 의존하지 않고 코드를 작성할 수 있게 한다.
  • geometry의 size 프로퍼티를 사용해서 view 의 너비와 높이를 가져온다. 
    그리고 0.7만큼 scale 을 낮춰서 frame 을 회전해도 사각형 안에 위치하도록 만든다. 
    SwiftUI는 바로바로 preview 를 통해 확인할 수 있데 해준다. 
  • image 또한 scaleEffect로 같은 scale 만큼 줄인다.

Other shapes

SwiftUI 는 다른 모양도 제공한다.

  • Circle: 원의 반지름은 사각형 frame 의 짧은 모서리의 반에 해당한다
  • Ellipse: frame 에 맞게 타원이 만들어 진다.
  • Rounded Rectangle: frame 에 맞게 타원이 만들어 진다.
  • Capsule: rounded rectangle 인데 corner radius 가 사각형의 짧은 모서리의 절반이다.

scale 이나 다른 effect 는 Rectangle 과 동일하게 적용된다.

복잡한 그림을 그릴땐 Paths 를 이용해라

Drawing lines with paths

custom shape 를 만들고 싶을 때 Paths를 사용한다. 

OverNightParkAward.swift 파일을 만들어서 도형을 그려본다.

이전과 동일하게 GeometryReader로 frame 에 관계없는 동적인 view 를 만들어준다.

처음 세 줄은 너비와 높이 사이의 더 작은 치수로 크기를 결정한다.
그런 다음 크기에 따라 근거리 및 원거리 값을 정의한다. 

마지막으로 Path 에 Color를 채워주면

.fill(Color.init(red: 0.4, green: 0.4, blue: 0.4))

Drawing dashed line

도로처럼 보이게 하기위해 중간에 점선을 그을 것 이다.

도로 shape 를 ZStack 으로 감싸고 아래에 점섬을 위한 코드를 작성한다.

차량 이미지도 추가한다.

Drawing arcs and curves

path 는 선을 그리는데 적합하다. 곡선을 그릴려면 arcs 와 quadratic curves 를 사용해야 한다.

AirportMealAward.swift 파일을 만든다.

Drawing quadratic curves

quadratic math (이차방정식) 공식에서 이름을 따왔다. SwiftUI는 수학적인 부분을 담당한다. 
이차곡선과 같이 3번째 점(control point) 로 당겨진 곡선을 생각하면 된다. 각 끝에서 곡선은 control point에 그려진 선과 평행하게 시작하고 모든 점 사이에서 부드럽게 곡선을 그린다.

addArc 메서드는 원의 부분을 그린다. 원의 중신과 반지름을 정하고 start angle 과 end angle, 시계방향을 알려주면 된다.

Fixing performance problems

SwiftUI 는 그래픽과 애니메이션을 CoreGraphics로 렌더링한다.
각각의 view를 필요할 때 그리는데 현재의 Apple 기기의 하드웨어는 여러개의 뷰를 성능저하 없이 처리할 수 있다.

하지만 어느 정도를 넘어서면 시스템에 과적해서 성능 저하를 확인할 수 있다.
만약 발생하면 drawingGroup modifier를 사용할 수 있다.
이 modifier는 SwiftUI 에게 view 내용을 off screen image 로 먼저 바꿔 놓게 해준다.

이 offscreen composition은 Metal 을 사용한다. 그래서 복잡한 화면에 대해 높은 성능을 낸다.

offscreen composition 은 오버헤드를 만들어 간단한 그래픽에서는 오히려 더 느리다

Key points

  • shape는 간단한 control 을 그릴 수 있는 방법을 제공한다.
    기본적으로 Rectangle, Circle, Ellipse, RoundedRectangle, Capsule 이 있다.
  • 디폴트로 Shape 에는 foreground color 가 입혀진다.
  • Shape는 solid 나 gradient color 로 채울 수 있다.
  • Gradient 는 transition으로 linear, radial, angular 이 있다,
  • rotationEffect는 shape 를 축에 따라 회전시킨다.
  • ZStack 은 공통되는 축에 따라 그래픽을 함친다. 
    그래픽과 이미지를 섞을 수 있다.
  • GeometryReader는 container에 맞게 그래픽이 그려질 수 있도록 해준다.
  • Paths는 기본 Shape 보다 더 복잡한 커브나 아치가 들어간 drawing 을 그릴때 사용한다.
  • 셰이프와 마찬가지로 셰이프를 수정하고 패스를 채울 수 있습니다.
  • drawGroup 은 무거운 그래픽 view의 성능을 향상시킬 수 있지만 오히려 단순한 view 에서는 느려진다

728x90

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

SwiftUI in UIKit vs UIKit in SwiftUI  (0) 2020.10.26
SwiftUI size rendering algorithm  (0) 2020.10.26
#12 Conditional Views  (0) 2020.10.23
#11 Lists & Navigation  (0) 2020.10.22
#10 Gestures  (0) 2020.10.22

댓글