├── Chapter ├── ch1 │ ├── README.md │ └── img │ │ ├── img_1.png │ │ ├── img_10.png │ │ ├── img_11.png │ │ ├── img_12.png │ │ ├── img_13.png │ │ ├── img_2.png │ │ ├── img_3.png │ │ ├── img_4.png │ │ ├── img_5.png │ │ ├── img_6.png │ │ ├── img_7.png │ │ ├── img_8.png │ │ └── img_9.png ├── ch1_Challenges │ ├── README.md │ └── img │ │ └── img_1.png ├── ch2 │ ├── README.md │ └── img │ │ ├── img_1.png │ │ ├── img_10.png │ │ ├── img_2.png │ │ ├── img_3.png │ │ ├── img_4.png │ │ ├── img_5.png │ │ ├── img_6.png │ │ ├── img_7.png │ │ ├── img_8.png │ │ └── img_9.png ├── ch2_Challenges │ ├── README.md │ └── img │ │ └── img_1.png ├── ch3 │ ├── README.md │ └── img │ │ ├── img_1.png │ │ ├── img_2.png │ │ ├── img_3.png │ │ ├── img_4.png │ │ ├── img_5.png │ │ ├── img_6.png │ │ ├── img_7.png │ │ └── img_8.png └── ch3_Challenges │ ├── README.md │ └── img │ ├── img_1.png │ └── img_2.png ├── README.md └── img └── img_1.png /Chapter/ch1/README.md: -------------------------------------------------------------------------------- 1 | 이 장에서는 애니메이션에 발을 담그게 됩니다. 2 | 하지만 제목에 현혹되지 마세요. 이렇게 강력하고 풍부한 APi로 시작하는 것은 다루어야 할 흥미로운 자료가 많다는 것을 의미합니다. 3 | 4 | 이 장및 관련 프로젝트에서 다음을 수행하는 방법에 대해 알아보겠습니다. 5 | 6 | - 멋진 애니메이션을 위한 stage를 만련하세요 7 | - 이동 및 fade Animation을 만듭니다. 8 | - 애니메이션 완화 기능을 조정합니다. 9 | - 애니메이션을 반전하고 반복합니다. 10 | 11 | 상당한 자료들이 있지만, 아주 재미있을 거라고 약속합니다. Are you up for the challenge? 12 | 13 | # Your first animation 14 | 15 | 이 장의 리소스 폴더에 있는 시작 프로젝트를 여십시오. Xcode로 프로젝트를 만들고 실행하면 다음과 같은 가상의 항공사 앱의 로그인 화면이 나타납니다. 16 | 17 |  18 | 19 | 이 앱은 현재 별로 효과가 없습니다. 아래에 제목, 두 개의 텍슽 필드, 큰 친근한 버튼이 있는 로그인 양식만 표시됩니다. 20 | 21 | 배경 사진도 좋고 구름도 네 개 있습니다. 구름은 clound1 ~ cloud4 코드는 이미 연결 되어 있습니다. 22 | 23 | ViewController.swift를 열고 내부를 확인하십시오. 파일 맨 위에 연결 된 모든 대상처와 클래스 변수가 표시됩니다. 또한 일부 UI를 초기화하는 View DidLoad()에 약간의 코드가 있습니다. 이 프로젝트는 여러분이 뛰어들어 상황을 조금 흔들어 볼 준비가 되어 있습니다! 24 | 25 | 소개를 충분히 해 보시기 바랍니다. 몇 가지 코드를 시험해 볼 준비가 되어 있다는 것은 의심의 여지가 없습니다! 26 | 27 | 첫 번째 작업은 사용자가 응용 프로그램을 열 때 화면 위에 양식 요소를 애니메이션화하는 것입니다. 이제 앱이 시작되면 양식이 표시되므로 view controller가 나타나기 바로 전에 화면 밖으로 옮겨야 합니다. 28 | 29 | 다음 코드를 viewWillAppear()에 추가 해 봅니다. 30 | 31 | ```swift 32 | heading.center.x -= view.bounds.width 33 | username.center.x -= view.bounds.width 34 | password.center.x -= view.bounds.width 35 | ``` 36 | 37 | 이렇게 하면 각 양식 요소가 화면의 보이는 경계 밖에 배치됩니다. 38 | 39 |  40 | 41 | 위의 코드는 ViewController가 나타나기 전에 실행되므로, 이러한 텍스트 필드는 처음부터 없었던 것처럼 보입니다. 42 | 43 | 프로젝트를 작성하고 실행하여 필드가 계획한 대로 실제로 화면에 표시 되도록 합니다. 44 | 45 |  46 | 47 | 잘 되었습니다. 이제 즐거운 애니메이션을 통해 폼 요소를 원래 위치로 다시 애니메이션 할 수 있습니다. 48 | 49 | 다음 코드를 viewDidAppear() 끝에 추가합니다. 50 | 51 | ```swift 52 | UIView.animate(withDuration: 0.5) { 53 | self.heading.center.x += self.view.bounds.width 54 | } 55 | ``` 56 | 57 | 제목을 애니메이션으로 표시하려면 UIView 클래스 메서드를 부릅니다. 58 | 59 | animate(withDurationLAnimations:). 애니메이션이 즉식 시작되고 0,5초 이상 애니메이션됩니다. 코드의 첫 번째 메서드 매개 변수를 통해 지속 시간을 설정합니다. 60 | 61 | 이렇게 하면 매우 쉽습니다. 애니메이션 종료 시 보기에 대한 모든 변경 내용이 Uikit에 의해 애니메이션 됩니다. 62 | 63 | 프로젝트를 만들고 실행 합니다. 제목 스라이드가 다음과 같이 깔금하게 제자리에 표시되어야 합니다. 64 | 65 |  66 | 67 | 그러면 나머지 양식 요소에서 애니메이션을 실행 할 수 있습니다. 68 | 69 | animation(withDuration:anmations:)는 class의 method이므로 특정 view하나만 애니메이션 할 수 있습니다. 70 | 71 | 다음 코드를 추가 합니다. 72 | ```swift 73 | self.username.center.x += self.view.bounds.width 74 | ``` 75 | 프로젝트를 빌드하고 다시 실행합니다. 사용자 이름 필드가 제대로 표시되는지 확인합니다. 76 | 77 |  78 | 79 | 두 가지 관전이 함께 애니메이션을 보는 것은 꽤 멋지지만, 두 개의 뷰를 동일한 거리에서 동일한 기간 동안 애니메이션하는 것은 다소 딱딱해 보입니다. 이렇게 완벽한 동기화로 킬봇만 이동합니다. 80 | 81 | 각 요소가 다른 요소들과 독립적으로 움직인다면 애니메이션 사이에 약간의 지연이 있었나? 82 | 83 | 먼저 방금 추가한 사용자 이름을 애니메이션하는 줄을 제거합니다. 84 | 85 | ```swift 86 | self.username.center.x += self.view.bounds.width 87 | ``` 88 | 89 | 그런 다음 아래에 코드를 viewDidAppear 및에 추가 합니다. 90 | 91 | ```swift 92 | UIView.animate(withDuration: 0.5, delay: 0.3, options: [], 93 | animations: { 94 | self.username.center.x += self.view.bounds.width 95 | }, 96 | completion: nil 97 | ) 98 | ``` 99 | 100 | 이 시간에 사용하는 class method는 낯설지만 애니메이션을 사용자 지정 할 수 있는 몇 가지 매개 변수가 더 있습니다. 101 | 102 | * withDuration: 애니메이션의 기간 103 | * delay: UIkit이 애니메이션을 시작하기 전에 대기 할 시간(초) 104 | * options: 애니메이션에 대한 여러 가지 측면을 사용자 정의 할 수 있습니다. 나중에 이 파라미터에 대해 자세히 알아보겠지만, 지금은 빈 []로 “특변한 옵션 없음”을 의미하는 것으로 전달 할 수 있습니다. 105 | * animations: 클로져 표현식은 애니메이션을 표현합니다. 106 | * completion: 애니메이션이 완료되면 실행됩니다. 이 파라미터는 종종 cleanup task?나 체인 형태로 차례로 수행하려는 경우에 종종 유용하게 사용 됩니다. 107 | 108 | 위에 추가한 코드에서 지연 시간을 0.3으로 설정하여 애니메이션이 제목 애니메이션보다 늦게 시작됩니다. 109 | 110 | 프로젝트를 만들고 실행합니다. 111 | 112 |  113 | 114 | 훨씬 나아 보이네요. 이제 암호 필드에 애니메이션만 하면 됩니다. 115 | 116 | 다음 코드를 뷰 하단에 추가합니다. 117 | 118 | ```swift 119 | UIView.animate(withDuration: 0.5, delay: 0.4, options: [], 120 | animations: { 121 | self.password.center.x += self.view.bounds.width 122 | }, 123 | completion: nil 124 | ) 125 | ``` 126 | 127 | 여기서 사용자 이름 필드의 애니메이션을 가장하여 조금 더 지연시켰을 뿐입니다. 128 | 129 | 프로젝트를 만들고 다시 실행하여 전체 애니메이션 시퀀스를 확인합니다. 130 | 131 |  132 | 133 | UIkit 애니메이션으로 화면 전체의 보기를 애니메이션화 하려면 이 모든 작업을 수행해야 합니다! 134 | 135 | 이것이 시작에 불과합니다. 이 장의 나머지 부분에서는 몇 가지 멋진 애니메이션 기술을 더 배울 것입니다! 136 | 137 | Animatable properties 138 | 139 | 이제 애니메이션이 얼마나 쉬운지 알았으니 이제 여러분은 어떻게 다른 방식으로 자신의 관점을 애니메이션화 할 수 있는지 알고 싶을 것입니다. 140 | 141 | 이 세션에서는 UIView의 애니메이션 적용 가능한 특성에 대한 개요를 설명한 다음 프로젝트에서 이러한 애니메이션을 탐색하는 과정을 안내합니다. 142 | 143 | 모든 view의 프로퍼티를 애니메이션 할 수 있는 것은 아니지만 가장 간단한 것부터 가장 복잡한 것까지 모든 view가 아래의 설명 처럼 만들 수 있습니다. 144 | 145 |  146 | 147 | 이 전 장과 같이 view의 position과 frame을 애니메이션 하여 view가 확장, 축소 또는 이동되도록 할 수있습니다. 다음은 view의 postion과 frame을 수정하는데 사용하는 프로퍼티 입니다. 148 | 149 | * bounds: 이 프로퍼티는 위치를 변경하는데 사용하는 속성입니다. 150 | * frame: 이 프로퍼티는 view를 이동하거나 scale하는데 사용하는 속성입니다. 151 | * center: 이 프로퍼티는 view를 새로운 위치에 이동 할 때 사용하는 속성입니다. 152 | 153 | UIkit의 size와 center 프로퍼티는 크기와 변경 할 수 있습니다. 즉, center.y로 view를 수직으로 이동 시킬 수 있고 frame.size.with로 view를 줄여 들게 할 수 있습니다. 154 | 155 |  156 | 157 | view의 background의 색과 반투명으로 설정하여 view의 content를 변경 할 수 있습니다. 158 | 159 | 160 | - backgoundColor: 이 프로퍼티는 UIKit이 시간이 지나면서 서서히 배경 색을 변경하게 합니다. 161 | - alpha: 이 속성을 변경하여 fade-in, fade-out 효과를 만듭니다. 162 | 163 |  164 | 165 | 위와 동일한 방법으로 크기 및 위치도 변경 할 수 있습니다. 166 | 167 | - transform: 이 프로퍼티는 블록 내에서 view의 회전, 크기 그리고 위치를 변경 할 때 사용합니다. 168 | 169 | These are affine transformations under the hood, which are much more powerful and allow you to describe the scale factor or rotation angle rather than needing to provide a specific bounds or center point. 170 | 171 | 이것들은 아주 기본적인 구성 요소처럼 보이지만, 당신은 복작한 애니메이션 효과를 보고 놀라 것입니다. 172 | 173 | #Animation options 174 | 175 | 애니메이션 코드를 보면, 파라미터 option을 []으로 전달 했습니다.option을 사용하면 UIKit이 애니메이션을 생성하는 방법을 사용자가 정의 할 수 있습니다. 애니메이션의 지속 시간과 지연 시간만 조정했을 뿐 아니라 애니메이션 매개 변수를 훨씬 더 효과적으로 제어 할 수 있습니다. 176 | 177 | 아래의 옵션 리스트는 UIViewAnimationOptions의 type 입니다. 애니메이션에 사용하기 위해 다양한 방법으로 결합 할 수 있습니다. 178 | 179 | Repeating 180 | 181 | 다음 두 가지 애니메이션 옵션을 먼저 살펴보겠습니다. 182 | 183 | * .repeat: 이 옵션은 애니메이션을 무한 루프 만듭니다. 184 | * .autoreverse: 이 옵션은 .repeat와 함께 포함합니다. 이 옵션은 반복적으로 애니메이션을 앞으로 재생한 다음 반대로 재생합니다. 185 | 186 | password field의 viewDidAppear()에 .repeat 옵션을 수정합니다. 187 | 188 | ```swift 189 | UIView.animate(withDuration: 0.5, delay: 0.4, 190 | options: [.repeat, .autoreverse], 191 | animations: { 192 | self.password.center.x += self.view.bounds.width 193 | }, 194 | completion: nil 195 | ) 196 | ``` 197 | 198 | repeat효과를 볼려면 빌드를 해봅니다. 199 | 200 |  201 | 202 | title field 과 username field만 화면 중간에 위치하지만 password field는 애니메이션이 영구적으로 됩니다. 203 | 204 | 위에서 변견한 것과 동이한 코드를 수정하여 옵션 파라미터 .repeat와 .autoreverse를 모두 사용합니다. 205 | 206 | ```swift 207 | UIView.animate(withDuration: 0.5, delay: 0.4, 208 | options: [.repeat, .autoreverse], 209 | animations: { 210 | self.password.center.x += self.view.bounds.width 211 | }, 212 | completion: nil 213 | ) 214 | ``` 215 | 216 | 둘 이상의 옵션을 사용하려면 성정 구문을 사용하고 쉼표로 구분된 모든 옵션을 나열하고 몰록을 대괄호로 묶어야 하는 방법을 참고하세요. 217 | 218 | Build and run your project again; this time the password field just can’t make up its mind about staying on the screen! 219 | 220 | #Animation easing 221 | 222 | 현실에서 모든 것이 갑자기 시작되거나 멈추는 것은 아니다. 자동차나 기차와 같은 물리적 물체는 목표 속도에 도달 할 때까지 천천히 가속하며, 그들이 벽에 부딪히지 않는 한, 그들은 최종 목적지에서 완전히 멈출 때까지 서서히 속도를 늦춥니다. 223 | 224 | 아래 이미지는 이 개념을 자세히 보여줍니다. 225 | 226 |  227 | 228 | 애니메이션을 보다 사실적으로 보이도록 하기 위해 시작 시 가속도를 구축하고 끝 전에 느려지는 것과 도일한 효과를 적용 할 수 있습니다. 일반적으로 ‘case-in’ 및 ‘case-out’이라고 합니다. 229 | 230 | 다음과 같은 네 가지 완화 옵션 중에서 선택 할 수 있습니다. 231 | 232 | - .curveLinear: 이 옵션은 애니메이션에 가속 또는 감속을 적용하지 않습ㄴ디ㅏ. 이 책에서 이 옵션을 사용 할 유일한 시간은 3장 ‘Transitions’의 마지막 challenge에서 입니다. 233 | - .curveEaseIn: 이 옵션은 애니메이션 시작 부분에 가속을 적용 합니다. 234 | - .curveEaseOut: 이 옵션은 애니메이션 끝에 감소을 적용합니다. 235 | - .curveEaseInOut: 이 옵션은 애니메이션 시작 부분에 가속도를 적용하고 애니메이션 끝 부분에 감속을 적용합니다. 236 | 237 | 이러한 옵션이 어떻게 애니메이션에 시각적 영향을 미치는지 더 잘 이해하기 위해 프로젝트의 몇 가지 옵션을 시도해 볼 수 있습니다. 238 | 239 | 다음과 같은 새 옵션을 사용하여 password field의 애니메이션 코드를 다시 한 번 수정합니다. 240 | 241 | ```swift 242 | UIView.animate(withDuration: 0.5, delay: 0.4, 243 | options: [.repeat, .autoreverse, .curveEaseOut], 244 | animations: { 245 | self.password.center.x += self.view.bounds.width 246 | }, 247 | completion: nil 248 | ) 249 | ``` 250 | 251 | 프로젝트를 만들고 실행합니다. 가장 오른쪽 위치에 도달 할 때가지 필드가 얼마나 부드럽게 감속하는지 확인한 후 화면 왼쪽으로 돌아갑니다. 252 | 253 |  254 | 255 | 이것은 여러분이 실제 세상에서 어떻게 움직이는지 예상하기 때문에 훨씬 더 자연스러워 보입니다. 256 | 257 | 이제 그 반대도 시도해 보세요. 위와 동일한 코드를 수정하여 .curveEaseOut 옵션을 다음과 같이 .curveEaseIn로 변경하여 필드가 여전히 화면 밖에서 있을 때 애니메이션을 쉽게 적용 할 수 있습니다. 258 | 259 | ```swift 260 | UIView.animate(withDuration: 0.5, delay: 0.4, 261 | options: [.repeat, .autoreverse, .curveEaseIn], 262 | animations: { 263 | self.password.center.x += self.view.bounds.width 264 | }, 265 | completion: nil 266 | ) 267 | ``` 268 | 269 | 프로젝트를 만들고 실행하십시오. 어떻게 필드가 기계적인 힘으로 돌아가는 관찰 합니다. (?) 이것은 주자연 스러워 보이고 이전의 애니메이션 만큼 시각적으로 즐겁지 않습니다. 270 | 271 | 마지막으로 .curveEaseInOut을 사용해 보십시오. 그것은 당신이 이미 알고 있는 두 가지 옵션을 하나의 매우 자연스럽게 보이는 완화로 경합합니다. 또한 .curveEaseInOut은 당신의 애니메이션에 적용되는 기본 완화 기능입니다. 272 | 273 | 다양한 애니메이션 옵션이 프로젝트에 어떤 영향을 미치는지, 움직임의 매끄럽고 자연스럽게 보이는 방법을 살펴보았습니다. 274 | 275 | 다음 단계로 이동하기 전에 재생하고 있던 코드 조각의 옵션을 []로 변경합니다. 276 | 277 | ```swift 278 | UIView.animate(withDuration: 0.5, delay: 0.4, 279 | options: [], 280 | animations: { 281 | self.password.center.x += self.view.bounds.width 282 | }, 283 | completion: nil 284 | ) 285 | ``` 286 | 287 | 이제 기본적인 애니메이션이 어떻게 작동하는지 알았으니 좀 더 눈부신 애니메이션 기법을 다룰 준비가 된 것입니다. 288 | 289 | A지점에서 B지점으로 애니메이션을 만드는 것은 매우 쉽습니다! 290 | 291 | 다음 chapter에서는 spring을 사용하여 애니메이션을 구동하는 방법을 살펴보겠습니다. 292 | 293 | 294 | -------------------------------------------------------------------------------- /Chapter/ch1/img/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch1/img/img_1.png -------------------------------------------------------------------------------- /Chapter/ch1/img/img_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch1/img/img_10.png -------------------------------------------------------------------------------- /Chapter/ch1/img/img_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch1/img/img_11.png -------------------------------------------------------------------------------- /Chapter/ch1/img/img_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch1/img/img_12.png -------------------------------------------------------------------------------- /Chapter/ch1/img/img_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch1/img/img_13.png -------------------------------------------------------------------------------- /Chapter/ch1/img/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch1/img/img_2.png -------------------------------------------------------------------------------- /Chapter/ch1/img/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch1/img/img_3.png -------------------------------------------------------------------------------- /Chapter/ch1/img/img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch1/img/img_4.png -------------------------------------------------------------------------------- /Chapter/ch1/img/img_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch1/img/img_5.png -------------------------------------------------------------------------------- /Chapter/ch1/img/img_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch1/img/img_6.png -------------------------------------------------------------------------------- /Chapter/ch1/img/img_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch1/img/img_7.png -------------------------------------------------------------------------------- /Chapter/ch1/img/img_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch1/img/img_8.png -------------------------------------------------------------------------------- /Chapter/ch1/img/img_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch1/img/img_9.png -------------------------------------------------------------------------------- /Chapter/ch1_Challenges/README.md: -------------------------------------------------------------------------------- 1 | # chapter1 Challenges 2 | 3 | # Challenges 4 | 5 | 이 장이 iOS에서 보기를 처음으로 애니메이션으로 만든 경우, 머리가 약간 회전 할 수 있습니다. 하지만 걱정하지 마세요, 여러분의 초기 기술이 무엇이든지 간에, 여러분은 단지 몇 장 만에 애니메이션에 숙달하는 길을 잘 갈 것이기 때문입니다. 6 | 7 | 하지만 현재로서는 아주 간단한 도전이 하나 있습니다. 8 | 9 | # Challenge 1: Fade in the clouds 10 | 11 | ViewController에는 cloud1, cloud2, cloud3, cloud4의 네가지 outlets을 가지고 있습니다. 작업은 application starts에서 이러한 작업을 희미하게 표시하는 것입니다. 12 | 13 | 솔루션의 정확한 형태에 대해 상당히 많이 결정 할 수 있지만, 다음과 같은 기존벅인 단계를 따라야 합니다. 14 | 15 | 1. ViewWillAppear()에서 네 개의 모든 cloud view에 대해 alpha 프로퍼티를 0.0으로 설정합니다. 16 | 2. ViewDidAppear()에서 animate(withDuration:delay:options:animations:completion:)를 개별로 실행하며 4개의 애니메이션 모두에 대해 0.5개의 재생 시간과 0.5, 0.7, 0.9, 1.1개의 지연 시간을 사용 할 경우 멋진 효과를 얻을 수 있습니다. 17 | 3. 각 애니메이션 closusre에서 각 cloud view의 alpha를 1.0으로 변경 합니다. 그러면 구름이 희미해집니다. 18 | 19 | 프로젝트를 실행 할 때 cloud를 애니메이션화하는 멋진 전환 효과를 차례로 확인해야 합니다. 20 | 21 |  22 | 23 | 화면의 모든 뷰는 잘 애니메이션 되어야 합니다. 거의 … 로그인 버튼이 활성화되지 않았습니다! 걱정하지마세요 그건 다음 장에서 고칠 겁니다. 24 | -------------------------------------------------------------------------------- /Chapter/ch1_Challenges/img/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch1_Challenges/img/img_1.png -------------------------------------------------------------------------------- /Chapter/ch2/README.md: -------------------------------------------------------------------------------- 1 | # Chapter2: Spring 2 | 3 | 앞 장에서는 UIkit으로 기본 애니메이션을 만드는 방법을 배웠습니다. 시작 및 종료 값을 기간, 지연 및 기타 옵션과 함께 제공함으로써 UIKit은 자동으로 애니메이션 만듭니다. 4 | 5 | 지금까지 애니메이션은 한 방향으로 유동적인 움직임이었습니다. view의 위치를 애니메이션화하면 다음과 같이 A 지점에서 B지점으로 쉽게 이동 할 수 있습니다. 6 | 7 |  8 | 9 | 이 chapter에서는 보다 복잡한 애니메이션을 만드는 방법을 알아보겠습니다. 이 애니메이션은 마치 뷰가 Spring에 연결된 것처럼 움직입니다. 10 | 11 |  12 | 13 | 기본 애니메이션을 A 지점에서 B지점ㅇ까지 가져다가 약간 흔들리면 애니메이션의 동작은 아래의 빨간색 화살표로 표시된 경로를 따릅니다. 14 | 15 |  16 | 17 | View는 점 A에서 점 B로 연결되지만 점 B를 작은 양만큼 overshoot합니다. 그런 View가 다시 B 지점으로 돌아가 이번에는 야간 더 낮게 overshoot됩니다. 이 앞 뒤로의 진동은 View가 B지점에서 정지 할 때까지 반복됩니다. 18 | 19 | 그것은 멋진 효과입니다. 그것은 여러분의 애니메이션에 산뜻한 실제 느낌을 더합니다. 이장에서는 UI에 재생성을 추가하는데 이 효과를 사용하는 방법을 설명합니다. 20 | 21 | # Spring animations 22 | 23 | 이전 장의 프로젝트를 계속 진행합니다. 1장의 연습( challenge 과제 )을 완료하지 않은 경우 2장이 리소스 폴더에서 시작 프로젝트를 가져와 시작합니다. 24 | 25 | 프로젝트를 만들고 실행합니다. 다음과 같이 앱이 열리는 즉식 화면에서 보기를 볼 수 있습니다. ( 로그인 버튼 제외 ) 26 | 27 |  28 | 29 | 작업은 이 화면의 마지막 non-animation 요소(로그인 버튼)를 관리하는 것입니다. 30 | 31 | ViewController.swift를 열고 ViewWillAppear() 하단에 다음 코드를 추가합니다. 32 | 33 | ```swift 34 | loginButton.center.y += 30.0 35 | loginButton.alpha = 0.0 36 | ``` 37 | 38 | 앞 장에서와 같이 버튼의 시작 위치를 y축에서 약간 낮게 설정하고 알파 값을 0으로 설정하여 보이지 않는 것으로 시작합니다. 39 | 40 | 이제 viewDidAppear()를 보고 다음 코드를 추가합니다. 41 | 42 | ```swift 43 | UIView.animate(withDuration: 0.5, delay: 0.5, 44 | usingSpringWithDamping: 0.5, initialSpringVelocity: 0.0, options: [], 45 | animations: { 46 | self.loginButton.center.y -= 30.0 47 | self.loginButton.alpha = 1.0 48 | }, completion: nil) 49 | ``` 50 | 51 | 이 코드에는 두 가지 핵심 포인트가 있습니다. 52 | 53 | 첫째, 두 가지 다른 속성을 동시에 활성화했습니다! 생각보다 쉬웠죠? 54 | 55 | 둘째, 새 애니메이션 메소드를 처음으로 사용했습니다. animate(withDuration:delay:usingSpringWithDamping:initialSpringVelocity:optio ns:animations:completion:) 그 메소드 이름을 빨리 말하는 것은 혀를 다치게 할 수도 있습니다! 56 | 57 | 위의 방법은 이전 장에서 사용했던 방법과 매우 유사하지만, 몇 가지 새로운 변수들을 자랑합니다. 58 | 59 | * usingSpringWithDamping: 애니메이션이 최종 상태에 가까워질 때 적용되는 damping 또는 감소량을 제어합니다. 이 파라미터는 0.0 ~ 1.0 사이의 값을 수용합니다. 0.0에 가까운 값은 bouncier animation을 생성하는 반면 1.0에 가까운 값은 뻣뻣하게 보이는 효과를 만듭니다. 이 값은 스프링의 ‘stiffness’으로 생각 할 수 있습니다. 60 | * initialSpringVelocity: 이것은 애니메이션의 초기 속도를 제어합니다. 1.0의 값은 애니메이션의 속도를 1초 동안 총 애니메이션 거리를 커버하도록 설정합니다. 값이 크고 작을수록 애니메이션의 속도가 더 높거나 낮아집니다. 61 | 62 | 프로젝트를 만들고 실행하십시오. 이제 button의 이동 방법을 확인하십시오 63 | 64 |  65 | 66 | 애니메이션 초기 속도가 0.0이고 neural damping은 0.5이므로 애니메이션이 눈길을 끌지 못합니다. 67 | 68 | 속도와 damping에 대해 몇 가지 다른 값을 시도하면 이 애니메이션을 약간 장식 할 수 있습니다. 69 | 70 | 지속 시간을 3.0으로, damping을 0.1로 변경합니다. 이것은 단지 당신이 정상적인 속도 대신에 느린 동작으로 당신의 변화의 영향을 관찰 할 수 있습니다. 71 | 72 | 프로젝트를 빌드하고 다시 실행하세요. button의 불투명도가 올라 갈 때 어떻게 변하는지 기록해 두세요. 그 이유는 스프링 동작은 애니메이션화되는 모든 속성에 영향을 주기 때문입니다. 이 동작은 버튼의 수직 위치와 alpha 값에 모두 영향을 미칩니다. 73 | 74 | 이제 initalSrpingVelocity를 1.0으로 설정하고 프로젝트를 빌드하고 다시 실행하세요. 75 | 76 |  77 | 78 | 버튼이 애니메이션화되거나 암호 필드를 벗어나면 버튼이 약간 더 튀어 오른다는 것을 알 수 있습니다. 이는 버튼의 이동 시작 부분에서 탄력이 더 커지고 최종 위치에 고정되는 데 더 오래 걸리기 때문이빈다. 79 | 80 | 이러한 매개 변수의 변화가 애니메이션의 모양과 느낌에 어떤 영향을 미치는지 이해 할 때까지 damping 및 속도에 대한 몇 가지 다른 값을 사용하여 재생하세요. 81 | 82 | 완료되면 속도 값을 다시 원래 값으로 설정하세요. 83 | 84 | ```swift 85 | UIView.animate(withDuration: 0.5, delay: 0.5, usingSpringWithDamping: 86 | 0.5, initialSpringVelocity: 0.0, options: [], animations: { 87 | self.loginButton.center.y -= 30.0 88 | self.loginButton.alpha = 1.0 89 | }, completion: nil) 90 | ``` 91 | 92 | # Animating user interactions 93 | 94 | 스프링 애니메이션을 보기 초기 배치로 제한 할 필요는 없습니다. 실제로 사용자 입력에 대한 응답으로 view를 애니메이션하면 인터페이스가 활성화 될 수 있습니다. 이섹션에서는 탭을 눌러 로그인 버튼을 애니메이션 합니다. 95 | 96 | login()함수에 다음 코드를 추가합니다. 97 | 98 | ```swift 99 | UIView.animate(withDuration: 1.5, delay: 0.0, usingSpringWithDamping: 100 | 0.2, initialSpringVelocity: 0.0, options: [], animations: { 101 | self.loginButton.bounds.size.width += 80.0 102 | }, completion: nil) 103 | ``` 104 | 105 | 위의 애니메이션은 button 너비를 1초 반 동안 80point 씩 증가시킵니다. damping이 0.2로 설정되었기 때문에 버튼이 상당히 튕겨집니다. 경계를 늘리면 왼쪽과 오른쪽의 frame이 커집니다. 106 | 107 | 프로젝트를 만들고 실행하세요. 애니메이션이 작동하는 것을 보려면 버튼을 누르세요. 108 | 109 |  110 | 111 | 버튼을 누르면 버튼이 커지며 깜박이는 방식으로 깜박입니다. 사용자에게 탭 피드백을 제공하는 깔끔한 방법입니다. 112 | 113 | 이제 이 애니메이션과 몇 가지 더 많은 스프링 동작을 결합하여 버튼을 실제로 사용 할 수 있습니다. 114 | 115 | 다음 코드를 login()함수에 추가합니다. 116 | 117 | ```Swift 118 | UIView.animate(withDuration: 0.33, delay: 0.0, usingSpringWithDamping: 119 | 0.7, initialSpringVelocity: 0.0, options: [], animations: { 120 | self.loginButton.center.y += 60.0 121 | }, completion: nil) 122 | ``` 123 | 124 |  125 | 126 | 정말 멋지네요. 하지만 여러분은 곧 애니메이션 마스터가 되고 있고 훨씬 더 잘 할 수 있다는 것을 알고 있습니다. 127 | 128 | 사용자 피드백을 제공하는 또 다른 좋은 방법은 색상 변경을 통해서이다. 버튼의 배경색 속성을 애니메이션하여 버튼을 움직이는 동안 색칠합니다. 129 | 130 | 애니메이션 종료 식 안에 마지막으로 추가한 애니메이션에 다음 코드를 추가합니다. 131 | 132 | ```swift 133 | self.loginButton.backgroundColor = 134 | UIColor(red: 0.85, green: 0.83, blue: 0.45, alpha: 1.0) 135 | ``` 136 | 137 | 프로젝트를 만들고 다시 실행하세요. 버튼 이동, 모양 변경 및 색 변경이 동시에 표시됩니다. 138 | 139 |  140 | 141 | 마지막으로 추가해야 할 피드백은 activity indicator 입니다. 로그인 버튼은 네트워크를 통해 사용자 인증을 시작하도록 되어 있으므로 activity indicator를 사용자에게 표시하여 진행 중인 작업이 있음을 알리는 것이 좋습니다. 142 | 143 | 스크롤를 위로 올려 viewDidLoad()에서 progress indicator를 찾습니다. UIacitivityIndicatorView에서 spinner가 포함되어 있어 사용 할 수 있습니다. 하지막 아직 볼 수 없습니다. 왜냐하면 alpha 값이 0.0으로 되어 있기 때문입니다. 144 | 145 | login()함수로 돌아가서 다음 코드를 마지막 애니메이션 종료 식에 추가 합니다. 146 | 147 | ```swift 148 | self.spinner.center = CGPoint( 149 | x: 40.0, 150 | y: self.loginButton.frame.size.height/2 151 | ) 152 | self.spinner.alpha = 1.0 153 | ``` 154 | 155 | 이 spinner 애니메이션은 왼쪽으로 약간 움직이며 서서히 사라집니다. 이것은 사용자의 주의를 끌고 그들의 요청이 처리되고 있다는 것을 그들에게 충분히 알릴 수 있어야 합니다. 156 | 157 | 프로젝트를 만들고 실행하세요. 최신 애니메이션의 최종 버전을 확인하세요. 158 | 159 |  160 | 161 | 잠시 시간을 내어 당신이 여기서 무엇을 성취했는지 생각해 보세요. 버튼 뷰에 3개의 동시 애니메이션을 추가하여 너비를 높이고 view를 아래로 이동하며 색상을 변경 할 수 있습니다. 162 | 163 | 또한 activity spinner에서 생기거나 희미하게 보이는 것도 button view의 하위 뷰이기 때문입니다. 164 | 165 | 모든 애니메이션은 UIKit에 의해 자동으로 결합되고 무결접 실행이 되어 하나의 유연한 시각 효과를 만듭니다. 166 | 167 | 애니메이션의 구현 세부 사항에 대해 걱정 할 필요가 없습니다. 대신 UIKit 덕분에 멋진 애니메이션을 디자인하고 사용자를 괴롭힐 수 있습니다. 168 | -------------------------------------------------------------------------------- /Chapter/ch2/img/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch2/img/img_1.png -------------------------------------------------------------------------------- /Chapter/ch2/img/img_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch2/img/img_10.png -------------------------------------------------------------------------------- /Chapter/ch2/img/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch2/img/img_2.png -------------------------------------------------------------------------------- /Chapter/ch2/img/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch2/img/img_3.png -------------------------------------------------------------------------------- /Chapter/ch2/img/img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch2/img/img_4.png -------------------------------------------------------------------------------- /Chapter/ch2/img/img_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch2/img/img_5.png -------------------------------------------------------------------------------- /Chapter/ch2/img/img_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch2/img/img_6.png -------------------------------------------------------------------------------- /Chapter/ch2/img/img_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch2/img/img_7.png -------------------------------------------------------------------------------- /Chapter/ch2/img/img_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch2/img/img_8.png -------------------------------------------------------------------------------- /Chapter/ch2/img/img_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch2/img/img_9.png -------------------------------------------------------------------------------- /Chapter/ch2_Challenges/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Chapter2: Challenges 3 | 4 | # Challenge 1: Convert text field animations to spring- animations 5 | 6 | UIKit 안의 spring 애니메이션 API와 표준? 애니메이션 매우 유사합니다. 따라서 username, password field에서 실행 중인 애니메이션을 스프링 애니메이션으로 변환하는 것은 큰 문제가 되지 않습니다. 7 | 8 | 이 과제를 완료하려면 다음을 수행해야 합니다. 9 | 10 | 1. userSpringWIthDamping 및 initialSpringVelocity 매개 변수를 사용자 이름 필드에 추가합니다. 스프링 초기 속대에 0.0을 사용합니다. 스프링 Damping의 경우 0.2, 0.6 및 0.9를 사용해 보고 스프링 효과와 가장 유사한 값을 선택합니다. 11 | 2. 선택한 Damping 및 속도를 사용하여 암호 필드 애니메이션에 대해서도 동일한 작업을 반복합니다. 12 | 13 |  14 | 15 | 그 책의 이 시점까지 당신은 봄 애니메이션의 탄탄한 기초를 얻었습니다. 이러한 유형의 애니메이션을 더 많이 사용하고 다양한 Damping 및 속도 조합을 실험 할 수록 자신의 앱에서 보는 뷰에 맞는 완벽한 스프링 애니메이션을 더욱 편리하게 디자인 할 수 있습니다. 16 | 17 | 다음 장으로 넘어 갈 준비가 되었습니까? 3장에서는 UIkit 전환에서 다음 유형의 애니메이션에 대해 배우게 됩니다. 18 | -------------------------------------------------------------------------------- /Chapter/ch2_Challenges/img/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch2_Challenges/img/img_1.png -------------------------------------------------------------------------------- /Chapter/ch3/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 3: Transitions (전환) 2 | 3 | 이 전 두 장에서 위치 및 alpha와 같은 View의 애니메이션 적용 가능한 프로퍼티를 기반으로 애니메이션을 만드는 방법을 배웠습니다. 하지만 View 추가 또는 제거를 애니메이션화 할 경우 어떻게 처리하시겠습니까? 4 | 5 | 이 전 장의 방법을 사용하고 인터페이스를 안팎으로 View를 애니메이션 할 수 있습니다. 그러나 이 장에서는 전환을 사용하여 View의 변경 사항을 애니메이션화하는 방법을 설명합니다. 6 | 7 | 변환은 보기에 적용 할 수 있는 미리 정의 된 애니메이션입니다. 이러한 미리 정의 된 애니메이션은 보기의 시작 상태와 종료 상태 사이를 보관하지 않습니다. 대신 다양한 상태 변화가 자연스럽게 보이도록 애니메이션을 디자인 할 수 있습니다. 8 | 9 | # Example transitions 10 | 11 | 전환 사용 시기를 더 잘 이해하기 위해 이 섹션에서는 전환 애니메이션을 사용 할 수 있는 다양한 애니메이션 시나리오를 안내합니다. 12 | 13 |  14 | 15 | 화면에서 새 View를 추가하려면 이전 장에서 사용한 것과 유사한 메서드를 호출합니다. 이번에는 미리 정의된 전환 효과 중 하나를 선택하고 애니메이션 contain View라고 하는 것을 애니메이션으로 만들 것입니다. 16 | 17 | 변환은 contain View를 애니메이션화하고 애니메ㅣ션이 실행 되는 동안 하위 View로 추가하는 모든 새 View가 나타납니다. 18 | 19 | Contain View를 애니메이션화하는 방법과 하위 View 간 전환을 실행 할 시기를 더 잘 설명하려면 다음 코드 조각들을 고려하세요. 20 | 21 | ``` swift 22 | var animationContainerView: UIView! 23 | override func viewDidLoad() { 24 | super.viewDidLoad() 25 | //set up the animation container 26 | animationContainerView = UIView(frame: view.bounds) 27 | animationContainerView.frame = view.bounds 28 | view.addSubview(animationContainerView) 29 | } 30 | override func viewDidAppear(_ animated: Bool) { 31 | super.viewDidAppear(animated) 32 | //create new view 33 | let newView = UIImageView(image: UIImage(named: "banner")) 34 | newView.center = animationContainerView.center 35 | //add the new view via transition 36 | UIView.transition(with: animationContainerView, 37 | duration: 0.33, 38 | options: [.curveEaseOut, .transitionFlipFromBottom], 39 | animations: { 40 | self.animationContainerView.addSubview(newView) 41 | }, 42 | completion: nil 43 | ) 44 | } 45 | ``` 46 | 47 | 이러한 가상 상황에서는 ViewController의 ViewDidload()에 animationContainView라는 새 View를 작성합니다. 그런 다음 이 Container를 배치하고 View에 추가합니다. 48 | 49 | 나중에 애니메이션 전환을 만들려면 애니메이션을 위한 새 View를 만듭니다. 여기서 newView라고 합니다. 50 | 51 | 전환을 생성하려면 transition(with: _ duration: _ options: _ animations: _ completion: _ ) 기존 UIView animation 방법과 거의 동일하지만 이 경우 전환 애니메이션의 ContainerVIew 역할을 하는 추가 매개변수가 View를 제공합니다. 52 | 53 | 여기서 새로운 애니메이션 옵션이 있습니다. .transitionFlipFormBottom입니다. 아직 보지는 못했지만, 이 것은 이 장의 도입에서 논의되는 미리 정의된 전환 중 하나입니다. .transitionFlifFromBottom은 뷰의 하단 가장자리가 View Flip?으로 사용되는 뷰를 Flip이라고 합니다. 54 | ( 55 | There’s a new animation option here, .transitionFlipFromBottom, which you haven’t seen yet. This is one of the predefined transitions discussed in the introduction of this chapter. .transitionFlipFromBottom flips the view over with the bottom edge of the view serving as the “hinge” around which the view flips. 56 | ) 57 | 58 | 마지막으로 애니메이션 클로져 내의 애니메이션에 하위 View를 추가하면 전환 중에 하위 View가 나타납니다. 59 | 60 | 사전 정의된 전환 애니메이션 옵션의 전체 목록은 다음과 같습니다. 61 | 62 | * .transitionFlipFromLeft 63 | * .transitionFlipFromRight 64 | * .transitionCurlUp 65 | * .transitionCurlDown 66 | * .transitionCrossDission 67 | * .transitionFlipFromtop 68 | * .transitionFlipFromBottom 69 | 70 |  71 | 72 | transition animation으로 화면에서 하위 View를 제거하는 것은 하위 View를 추가하는 것과 같습니다. transition animation으로 이 작업을 수행하려면 애니메이션 종료 식 내에서 다음과 같이 간단히 removewFromSuperview()라고 하면 됩니다. 73 | 74 | ``` swift 75 | //remove the view via transition 76 | UIView.transition(with: animationContainerView, duration: 0.33, 77 | options: [.curveEaseOut, .transitionFlipFromBottom], 78 | animations: { 79 | self.newView.removeFromSuperview() 80 | }, 81 | completion: nil 82 | ) 83 | ``` 84 | 85 | 이전 예에서와 같이 래퍼 변환은 Flip animation을 수행하며 새 View가 모두 끝나면 사라집니다. 86 | 87 |  88 | 89 | 지금까지 View 계층을 변경하는 Transition에 대해서만 배웠습니다. 따라서 Transition 시 Container View가 필요했습니다. 즉, 계층 변경이 context에 적용됩니다. 90 | 91 | 반대로 숨겨서 표시 할 Container View를 설정 할 필요가 없습니다. 이 경우 Transition은 View 자체를 animation Container로 사용합니다. 92 | 93 | Transition을 사용하여 하위 View를 숨기려면 다음 코드를 고려하세요. 94 | 95 | ``` swift 96 | //hide the view via transition 97 | UIView.transition(with: self.newView, duration: 0.33, 98 | options: [.curveEaseOut, .transitionFlipFromBottom], 99 | animations: { 100 | self.newView.isHidden = true 101 | }, 102 | completion: nil 103 | ) 104 | ``` 105 | 106 | 여기서 Transition의 첫 번째 인수로 표시하거나 숨기려는 View를 전달 합니다. 그런 다음 애니메이션 블록과 음성에서 View의 IsHidden 속성을 설정하면 Transition 애니메이션이 시작됩니다. 107 | 108 |  109 | 110 | 한 View를 다른 View로 교체하는 것도 쉬운 방법입니다. 기존 View를 첫 번째 인수로 전달하고 toView: 매개변수를 아래와 같이 교체하려는 View로 설정합니다. 111 | 112 | ``` swift 113 | //replace via transition 114 | UIView.transition(from: oldView, to: newView, duration: 0.33, 115 | options: .transitionFlipFromTop, completion: nil) 116 | ``` 117 | 118 | UIkit이 여러분에게 얼마나 많은 도움을 주는지 꽤 명확해지고 있습니다. 119 | 120 | 이 장의 나머지 부분에서는 Transition을 통해 UI 요소를 표시하고 숨기고 자신의 프로젝트에 가져 올 수 있는 몇 가지 새로운 애니메이션 기술을 배웁니다. 121 | 122 | Mixing in transitions 123 | 124 | 이 장에서 Bagama Air login screen project 작업을 계속 할 것입니다. 이미 로그인 양식에 스피너를 추가하고 버튼을 누르기 위해 이 화면의 View에 많은 매력적인 애니메이션을 만들었습니다. 125 | 126 | 그런 다음 사용자 인증을 시뮬레이션하고 여러 가지 진행 상황 메시지를 애니메이션화합니다. 로그인 버튼을 누르면 ‘연결…’, ‘인증…’, ‘실패’등의 메시지가 표시됩니다. 127 | 128 |  129 | 130 | 이전 장을 수행하지 않은 경우 이 장의 리소스 폴더에서 시작 프로젝트로 시작 할 수 있습니다. 만약 여러분이 자신의 프로젝트에서 마지막 몇 장의 예를 따른다면, 아주 잘 한 일입니다. 기존 프로젝트로 계속 할 수도 있습니다. 131 | 132 | ViewController.swift를 열고 ViewDidLoad()를 확인합니다. 이 방법의 일부는 클래스 변수 상태에 저장된 hidden image view를 추가합니다. 133 | 134 | status를 사용하여 사용자에게 진행 메시지를 표시합니다. 메시지는 시작 프로젝트에 포함된 또 다른 클래스 변수인 메시지 배열에서 전송됩니다. 135 | 136 | 다음 메소드를 ViewController에 추가합니다. 137 | 138 | ``` swift 139 | func showMessage(index: Int) { 140 | label.text = messages[index] 141 | UIView.transition(with: status, duration: 0.33, 142 | options: [.curveEaseOut, .transitionCurlDown], 143 | animations: { 144 | self.status.isHidden = false 145 | }, 146 | completion: {_ in 147 | //transition completion 148 | } ) 149 | } 150 | ``` 151 | 152 | 이 method는 인텍스라는 매개 변수를 사용하며, 이 매개 변수는 인텍스를 기준으로 레이블 값을 메시지 내용에 설정하는 데 사용됩니다. 153 | 154 | 다음으로 transition(with:duration:options:animations: completion:) 을 호출합니다. 배너를 설정한 상태로 표시하기 위해 애니메이션 블록 내에서 배너를 false으로 숨깁니다. 155 | 156 | 위의 또 다른 새로운 애니메이션 옵션이 있습니다. .transitionCurlDown. 이러한 transition은 종이가 법률용 패드에서 뒤집혀지는 것처럼 View를 애니메이션화하며 다음과 같습니다. 157 | 158 |  159 | 160 | 새로운 showMessage(index:) 메소드를 연습 할 때 입니다. login()에서 다음 코드를 찾습니다. 161 | 162 | ``` swift 163 | animations: { 164 | self.loginButton.bounds.size.width += 80.0 165 | }, completion: nil) 166 | ``` 167 | 168 | 기존 애니메이션 블록으로 사용자가 탭 할 때 로그인 단추가 되돌아 갑니다. 이 애니메이션에 message(index:)를 표시하는 새로운 conpletion closure를 추가합니다. 169 | 170 | 완료의 nil 인수 값을 다음 closure로 바꿉니다. 171 | 172 | ``` swift 173 | completion: { _ in 174 | self.showMessage(index: 0) 175 | } 176 | ``` 177 | 178 | 닫기는 하나의 bool파라미터 변수를 사용합니다. 이 매개 변수는 애니메이션이 성공적 완료되었는지 아니면 애니메이션이 완료되기 전에 취소되었는지 나타냅니다. 179 | 180 | closure 내에서 단순히 showMessage with index 0을 호출하여 메시지 배열의 첫 번째 메시지를 표시합니다. 181 | 182 | 프로젝트를 만들고 실행하십세요. 로그인 버튼을 누르면 상태 배너가 첫 번째 진행 메시지와 함께 나타납니다. 183 | 184 |  185 | 186 | 그 현수막이 종이처럼 휘어지는 거 봤나요? 이것은 보통 정적 텍스트 레이블로 표시되는 메시지에 주의를 기울이는 매우 좋은 방법입니다. 187 | 188 | 다음 애니메이션의 경우 다음 배너를 올바른 위치에 배치 할 수 있도록 먼저 배너의 초기 위치를 저장해야 합니다. 189 | 190 | 다음 코드를 ViewDidLoad 끝 부분에 추가하여 배너 초기 위치를 statusPosition이라는 속성에 저장합니다. 191 | 192 | ``` swift 193 | statusPosition = status.center 194 | ``` 195 | 196 | 이제 View animation transition의 혼합을 구상 할 수 있습니다. 197 | 198 | 다음 메소드를 추가 하여 표준으로 화면에서 status message를 제거합니다. 199 | 200 | ``` swift 201 | func removeMessage(index: Int) { 202 | UIView.animate(withDuration: 0.33, delay: 0.0, options: [], 203 | animations: { 204 | self.status.center.x += self.view.frame.size.width 205 | }, 206 | completion: { _ in 207 | self.status.isHidden = true 208 | self.status.center = self.statusPosition 209 | self.showMessage(index: index+1) 210 | } 211 | ) } 212 | ``` 213 | 214 | 위의 코드에서 당신은 오랜 된 것을 사용합니다. 215 | 216 | ``` swift 217 | animate(withDuration:delay:options:animations:completion:)을 사용하여 화면 바로 바깥으로 status를 이동합니다. 218 | ``` 219 | 220 | complete에서 애니메이션이 완료되면 status를 원래 위치로 다시 이동하고 숨깁니다. 마지막으로 showMessage에 다시 transition하지만, 이번에는 표시 할 메시지의 색을 전달 합니다. 221 | 222 | 표준 애니메이션을 전환과 결합하는 것은 매우 쉽습니다. 단순히 적절한 PAI를 호출하고 UIKIT은 배그라운드에서 해당 CoreAnimation 비트를 호출합니다. 223 | 224 | 이제 showMessage와 removeMessage 사이의 통화 체인을 완료하여 실제 인증 프로세스를 모방해야 합니다. 225 | 226 | showMessage(index:)를 찾아 주석 // transition completion을 다음 코드로 바꿉니다. 227 | 228 | ``` swift 229 | delay(2.0) { 230 | if index < self.messages.count-1 { 231 | self.removeMessage(index: index) 232 | } else { 233 | //reset form 234 | } 235 | } 236 | ``` 237 | 238 | transition이 완료되면 2.0초 동안 기다렸다가 남아 있는 메시지가 있는지 확인합니다. 이 경우 removeMessage(index:)를 통해 현재 메시지를 제거합니다. 그런 다음 removeMessage(index:)의 compleste 블록에서 showMessage(index:)를 호출하여 다음 메시지를 순서대로 표시합니다. 239 | 240 | 프로젝트를 한 번 더 작성하고 실행하세요. 이렇게 인증 진행 메시지가 업데이트로 되는 애니메이션 시퀀스를 즐기세요. 241 | 242 |  243 | 244 | Transition은 3D 스타일 애니메이션을 UIKIT에서 만드는 유일한 방법이기 때문에 비유적인 도구 상자에서 보관하기 위한 작지만 중요한 애니메이션 지식의 집합입니다. 245 | 246 | 보다 정교한 3D 효과를 알고 싶으시다면 VI섹션 “3D 애니메이션”에서 핵심 애니메이션과 3D layer Transitin을 자세히 설명 할 수 있는 기회를 드립니다. 247 | 248 | 다음 섹션으로 이동하기 전에 이 장의 과제를 시도해 보세요. 지난 세 장에서 애니메이션에 대해ㅔ 많은 것을 배웠기 때문에, 한 가지 도전은 충분하지 않습니다. 저는 여러분에게 세가지를 주었습니다. 249 | 250 | 이러한 과제를 통해 Bahama Air login Screen에서 개발을 마뤼 하고 첫 번째 über haxx0r 과제를 수행 할 수 있습니다. 251 | -------------------------------------------------------------------------------- /Chapter/ch3/img/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch3/img/img_1.png -------------------------------------------------------------------------------- /Chapter/ch3/img/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch3/img/img_2.png -------------------------------------------------------------------------------- /Chapter/ch3/img/img_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch3/img/img_3.png -------------------------------------------------------------------------------- /Chapter/ch3/img/img_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch3/img/img_4.png -------------------------------------------------------------------------------- /Chapter/ch3/img/img_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch3/img/img_5.png -------------------------------------------------------------------------------- /Chapter/ch3/img/img_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch3/img/img_6.png -------------------------------------------------------------------------------- /Chapter/ch3/img/img_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch3/img/img_7.png -------------------------------------------------------------------------------- /Chapter/ch3/img/img_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch3/img/img_8.png -------------------------------------------------------------------------------- /Chapter/ch3_Challenges/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 3: Challenges 2 | 3 | Challenge 1: Pick your favorite transition 4 | 5 | 지금까지 내장된 전환 애니메이션 중 하나만 보셨을 것입니다. 다른 사람들이 어떻게 생겼는지 궁금하지 않아요? 6 | 7 | 이 과제에서는 사용 가능한 다른 transition 애니메이션을 모두 시도해보고 즐겨찾기를 사용하여 진행 메시지 배너를 애니메이션 할 수 있습니다. 8 | 9 | ViewController를 열고 message(index:)에서 transition 애니메이션 .transitionCurlDown 구체적으로 명시 하세요. 10 | 11 | ``` swift 12 | UIView.transitionWithView(status, duration: 0.33, options: 13 | [.curveEaseOut, .transitionCurlDown], animations: ... 14 | ``` 15 | 16 | .transitionCurlDown을 사용 가능한 다른 transition 애니메이션으로 교체한 다음 프로젝트를 빌드하고 실행하여 애니메이션의 모양을 확인합니다. 다음은 사용 가능한 transition 목록입니다. 17 | 18 | ``` swift 19 | .transitionFlipFromLeft 20 | .transitionFlipFromRight 21 | .transitionCurlUp 22 | .transitionCurlDown 23 | .transitionCrossDissolve 24 | .transitionFlipFromTop 25 | .transitionFlipFromBottom 26 | ``` 27 | 28 | 이 화면의 다른 애니메이션과 가장 잘 맞는 것은 무엇이라고 생각하십니까? 29 | 30 | 즐겨 찾는 것이 없다면 내가 가장 좋아하는 .transitionFlipFromBottom을 사용보세요. 배너 그래픽과 잘 맞는 것 입니다. 31 | 32 |  33 | 34 | Challenge 2: Reset the form to its initial state 35 | 36 | 이 문제를 해결하려면 로그인 단추를 누른 후 실행 되는 모든 애니메이션을 실행 취소하여 양식을 초기 상태로 재설정합니다. 이렇게 하면 로그인에 실패하면 로그인 단추를 두 번쨰로 누르면 모든 애니메이션이 다시 발생하는 것을 볼 수 있습니다. 37 | 38 | 다음은 이 과제를 완료하는 데 필요한 일반적인 단계 목록입니다. 39 | 40 | 1. 빈 메서드 resetForm()을 새로 만들고 자리 표시자 설명이 있는 코드에서 호출합니다. 41 | 2. resetForm()에서 transition(with: _ duration: _ option: _ animations: _ completion: _)을 사용하여 상태 가시성을 hidden으로 설정하고 중심을 self.statusPosition으로 설정합니다. 이렇게 하면 배너가 초기 상태로 재설정됩니다. 해당 전환에서 대해 0.2초 기간을 사용합니다. 42 | 3. 당신의 배너를 숨기는 전환은 배너를 보여주는 애니메이션의 정반대 애니메이션을 사용하는 것이 좋을 것입니다. 예를 들어 .transitionCurlDown을 통해 배너르 ㄹ표시하는 경우 .transitionCulrUp을 사용하여 배너를 숨깁니다. .transitionFlipFormBottom의 역방향은 transitionFlipFromTop …등이 될 것입니다. 43 | 4. 그런 다음 animate(withDuration: _ delay: _ options: _ animations: _ completion: _ )의 resetForm()을 내부에서 만듭니다. 44 | * loginButton의 indicator를 self.spinner를 원래 위치 (-20.0, 16.9)로 이동합니다. 45 | * self.spinner의 알파 속성을 0.0으로 설정하여 숨깁니다. 46 | * 로그인 버튼의 배경색을 원래 값으로 다시 색칠합니다.( UIColor( red: 0.63, green: 0.84, blue: 0.35, alpha: 1.0) 47 | * 계속해서 로그인 버튼에 대한 모든 변경 사항을 bounds.size.width의 속성을 80으로 감소시킵니다. 48 | * 마지막으로 버튼을 비밀번호 필드 아래의 원래 지점으로 다시 이동시키고 center.y를 60.0으로 감소 시킵니다. 49 | 50 | 인증 프로세스에서 모든 애니메이션을 정확하게 반전시킨 경우 모든 인증 메시지가 표시되면 다음과 같이 애니메이션해야 합니다. 51 | 52 |  53 | -------------------------------------------------------------------------------- /Chapter/ch3_Challenges/img/img_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch3_Challenges/img/img_1.png -------------------------------------------------------------------------------- /Chapter/ch3_Challenges/img/img_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jungseungyeo/iOS-Animation/f9ee544e54ffacb464685e49f5e79c9a9b1b23de/Chapter/ch3_Challenges/img/img_2.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOS-Animation 2 | 3 | iOS 애니메이션 시작합니다. 4 | 5 | ------ 6 | 7 | ## 책 소개 8 | 9 | - [iOS Animations by Tutorials](https://store.raywenderlich.com/products/ios-animations-by-tutorials) 10 | 11 |  12 | 13 | - Platform : iOS 11 14 | - Laguage: Swift 4 15 | - Tool: Xcode 9 16 | 17 | ## Chapter 소개 18 | --- 19 | 20 | ### Session 1 ( 1 장 ~ 5 장 ) 21 | 22 | |