2021. 10. 23. 12:50ㆍUIKit, SwiftUI, H.I.G
1️⃣ 그라데이션을 만들기 위해 필요한 CAGradientLayer?
커스텀 탭바에는 그라데이션도 적용되어 있었다. (괜찮아 이쁘잖아)
그래서 지난번 블러 효과를 다룬 글에 이어서, 이번에는 그라데이션을 적용하는 방법에 대해서 다뤄보도록 하겠다.
그라데이션을 사용하기 위해서는 CAGradientLayer에 대한 이해가 필요했다.
이해하기 위해 역시 Apple 개발자 공식문서를 읽어보자면,
CAGradientLayer는 CALayer를 상속받으며, 배경색 위 색상 그라데이션을 그려 둥근 모서리를 포함한 레이어를 채우는 방식이라 쓰여있다.
💡 여기서 잠깐! CALayer란 무엇일까?
CA는 Core Animation의 줄임말이다.
간단하게 말해, UIView에서는 레이아웃, 터치 이벤트 같은 처리를 하면서 많은 작업을 하기 때문에 애니메이션을 담당하는 행위를 Core Animation, 즉 CALayer에게 일을 분산(위임) 해주게 되었다고 보면 된다.
(모서리를 둥글게 만드는 cornerRadius를 layer에서 담당하는 것이 이 이유 때문이라 볼 수 있다.)
-> 그렇기 때문에 모든 UIView는 하나의 (Root) CALayer를 가질 수 있을 것이며,
추가로 더해, (Root) CALayer는 (하위) SubLayer를 여러 개 가질 수 있다.
CAGradientLayer의 프로퍼티로 사용할 수 있는 것들이 5가지가 있는데 많지 않아서 하나씩 살펴보겠다.
계속 지점(정지점)이라는 말이 반복해서 나오는데, 이거는 일종의 기준(점)이라 이해하면 되며, 모든 점은 Layer를 그리는 뷰 기준으로 0.0부터 1.0 사이의 값으로 설정된다. (더 자세한건 아래에서 알아보도록 하자)
- var colors: [Any]? -> 각 gradient 점에 지정할 색을 Array로 설정
- var locations: [NSNumber]? -> Gradient가 적용될 지점의 위치를 정의
- var endPoint: CGPoint -> Gradient의 끝 지점을 정의
- var startPoint: CGPoint -> Gradinent의 시작 지점을 정의
- var type: CAGradientLayerType -> Gradient
이를 바탕으로 내가 탭바에서 사용했을 때, 그라디언트 코드를 쉽게 사용하기 위해 아래와 같은 Extension 코드를 작성했다.
extension UIView {
func setGradient(color1: UIColor, color2: UIColor) {
let gradient: CAGradientLayer = CAGradientLayer()
gradient.colors = [color1.cgColor, color2.cgColor]
gradient.locations = [0.0, 1.0]
gradient.startPoint = CGPoint(x: 0.5, y: 0.0)
gradient.endPoint = CGPoint(x: 0.5, y: 1.0)
gradient.frame = bounds
gradient.cornerRadius = 35
layer.addSublayer(gradient)
}
}
그리고 실제 탭바에서 사용은 이런 식으로 사용했다.
customTabBar.setGradient(color1: UIColor(red: 1, green: 1, blue: 1, alpha: 0.35),
color2: UIColor(red: 1, green: 1, blue: 1, alpha: 0.15))
2️⃣ Gradient의 시작과 끝 지점(startPoint, endPoint) 차이에 따른 변화
이제 조금 더 깊게 그라데이션이 적용되는 지점을 설정하는 방법에 대해서 하나씩 자세하게 살펴보도록 하겠다.
우선 startPoint와 endPoint는 그라디언트의 적용 시작 지점과 끝 지점을 의미한다고 위에서 말했었다.
범위는 0.0부터 1.0까지의 CGPoint 값 (= x와 y값을 가진다)으로 지정하게 되는데, 가장 왼쪽 상단 (0.0, 0.0)부터 아래쪽 하단 (1.0, 1.0)까지 이루어진다고 보면 된다.
startPoint와 endPoint는 그라데이션의 적용 시작과 끝의 위치를 나타내기도 하지만,
그것보다 더 중요한 것은 여기서 지정하는 값에 따라 "그라데이션의 적용 방향"이 달라진다는 것을 살펴보고 넘어갈 필요가 있다.
기본적으로 startPoint와 endPoint값을 지정하지 않으면 start: (0.5, 0.0), end: (0.5, 1.0) 값이 담기게 되는 경우를 살펴보면,
아래와 같이 x축의 변화는 없이 위에서부터 아래 방향대로 그라데이션이 적용된다.
gradient.startPoint = CGPoint(x: 0.5, y: 0.0)
gradient.endPoint = CGPoint(x: 0.5, y: 1.0)
반대로 시작 포인트와 끝 포인트에 대해 y축에 변화없이 x축에 대한 변화만 주는 경우, 왼쪽에서 오른쪽 방향으로 그라데이션이 적용되는 것을 볼 수 있겠다.
*이때 y를 아래 코드처럼 (0.5 -> 0.5)로 이동을 시키나 (0.0 -> 0.0) 또는 (1.0 -> 1.0)으로 이동을 시키나 적용되는 그라데이션은 변화가 없다. (시작점의 관점에서는 숫자가 의미가 있겠지만, 방향의 관점에서는 start에서 end까지의 변화가 중요하므로 숫자 자체는 의미가 없다.)
gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
그렇다면 이 기본 개념을 활용한다면,
단순히 직선 방향이 아니라 대각선 방향으로도 그라데이션을 지정할 수 있고, 뷰 전체가 아닌 일부 부분에 대해서만 그라데이션을 적용시킬 수도 있을 것이다. 아래에서 확인해보자!
3️⃣ Gradient의 Locations 차이에 따른 변화
이번에는 locations 배열의 값을 바꿔보면서 "그라데이션이 적용되는 지점/위치"가 어떻게 바뀌는지 살펴보겠다.
기본적으로는 [0.0, 1.0]까지의 범위가 선택되어 뷰 전체에 자연스러운 그라데이션이 지금까지 적용되었는데,
이번에는 임의로 0.4부터 0,6까지의 범위로 그라데이션이 적용되는 지점을 지정해주게 되면, 아래와 같이 똑같은 시작점과 끝점을 지정해줬다고 하더라도 다른 그라데이션이 적용되는 것을 볼 수 있을 것이다.
*다시 한번, 위에서 지정한 시작점과 끝점은 그라데이션의 "방향"을 결정한다는 의미로 바라보는 것이 더 적합하다는 점! 리마인드.
gradient.locations = [0.4, 0.6]
단, 여기서 주의할 점은 범위를 오름차순이 아닌 "내림차순"으로 주면 그라데이션이 올바르게 적용되지 않는다는 것이다.
그라데이션의 시작점이 끝 부분에 있으니 이후 적용시킬 범위 자체가 없는 셈!
gradient.locations = [1.0, 0.0]
4️⃣ Gradient Type에 따른 변화
그라데이션 타입 (CAGradientLayerType)은 세 가지 종류가 있다.
- axial : 시작점에서 끝점까지 선형으로 적용되는 그라데이션, default로 적용되는 타입이다.
- conic : 중심을 기준으로 원형으로 회전하는 그라데이션, 뷰의 중심에서 시작해 각도에 따라 색상이 변화되는 형태
- radial : 중심에서 바깥 방향으로 적용되는 그라데이션, 원형 그라데이션을 만들 때 자주 사용된다.
위의 설명이나 아래 적용된 모습들을 보면 알겠지만,
axial을 제외한 conic과 radial은 "중심을 기준"으로 회전하거나 바깥 방향으로 회전하는 효과가 적용되기 때문에 startPoint와 endPoint를 잡을 때 실제 안쪽과 바깥쪽의 점을 각각 정확히 잡아야지만 그라데이션이 정상적으로 적용될 것이다.
5️⃣ Reference
'UIKit, SwiftUI, H.I.G' 카테고리의 다른 글
[UITapGestureRecognizer] UIGestureRecognizer 2탄 - Tap Gesture로 키보드 내리기 + 모달창 끄기 (0) | 2021.11.06 |
---|---|
[UIPanGestureRecognizer] UIGestureRecognizer 1탄 - 아래로 드래그해서 모달창 dismiss하는 방법 (0) | 2021.10.31 |
[UIVisualEffectView] UIBlurEffect로 블러 효과를 적용해보자 (0) | 2021.10.22 |
[UIView] 카드를 뒤집어보자 (transition animation) (1) | 2021.10.16 |
[UIAlertController] UIAlertController 기본 사용법부터 커스텀 방법까지 모두 정리해보자 (0) | 2021.10.01 |