Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- swiftUI
- rxswift
- HIG
- 애니메이션
- ribs
- 리팩토링
- collectionview
- Human interface guide
- uiscrollview
- clean architecture
- combine
- MVVM
- 리펙토링
- Protocol
- Observable
- 스위프트
- swift documentation
- SWIFT
- UITextView
- Refactoring
- RxCocoa
- UICollectionView
- uitableview
- map
- 리펙터링
- 클린 코드
- tableView
- Clean Code
- Xcode
- ios
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] Shimmer 애니메이션 (CABasicAnimation, CAGradientLayer) 본문
iOS 응용 (swift)
[iOS - swift] Shimmer 애니메이션 (CABasicAnimation, CAGradientLayer)
jake-kim 2022. 4. 4. 23:48
CABasicAnimation
- layer에 관련된 싱글-키프레임 애니메이션
- 모든 뷰들이 가지고 있는 CALayer에 애니메이션을 줄 수 있는 방법이며, 뷰를 이동시키거나, 흐리게하거나 등의 다양한 기능 구현 가능
- opacity
- colors
- locations
- fillColor
- strokeEnd
- rotation
- 기타 모든 종류의 키들을 extension으로 구현해놓은 아래 링크 참고
cf) CAKeyFrameAnimation도 위 종류들을 모두 사용할 수 있고, 레이어의 여러 프레임에 대한 작업에 사용되고 CABasicAnimation은 단일 키프레임에 대한 애니메이션 기능을 제공
- 사용 방법
- layer에 CABasicAnimation 인스턴스를 추가하여 사용
self.someView.layer.add(animation, forKey: animation.keyPath)
Shimmer 구현 방법 (CABasicAnimation 사용)
- UIView을 extension하여 사용
extension UIView {
func animateShimmer() {
}
}
- shimmer에 사용할 layer가 필요하고, 이 layer는 gradient되어 있으므로 CAGradientLayer 생성하여 layer에 삽입
// in animateShimmer()
let gradientLayer = CAGradientLayer()
let gradationColor = [UIColor.clear, .white.withAlphaComponent(0.3), .clear]
gradientLayer.frame = self.bounds
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
gradientLayer.colors = gradationColor.map { $0.cgColor }
gradientLayer.locations = [0.0, 0.5, 1.0]
self.layer.addSublayer(gradientLayer)
- CABasicAnimaion인스턴스를 만들어서 위 layer에 추가
- 주의: repeat 사이의 delay는 줄 수 없기 때문에, 만약 delay를 주고 싶은 경우 repeatCount=1로 하고, 외부에서 timer를 돌릴것
// in animateShimmer()
// keyPath: locations 속성 이용 (opacity, borderColor 등 종류가 다양)
let animation = CABasicAnimation(keyPath: "locations")
// 보간 사용 (0.0 ~ 1.0이 원래 layer 색깔이고 멀어질수록 보간법 적용)
animation.fromValue = [-0.7, -0.5, 0.0]
animation.toValue = [1.0, 1.3, 1.7]
animation.repeatCount = .infinity
animation.duration = 1.5
// timingFunction을 통해 easeIn, easeOut, linear 등 설정 가능
animation.timingFunction = CAMediaTimingFunction(name: .easeIn)
// layer에 애니메이션 추가
gradientLayer.add(animation, forKey: animation.keyPath)
- 전체 코드
extension UIView {
func animateShimmer() {
let gradientLayer = CAGradientLayer()
let gradationColor = [UIColor.clear, .white.withAlphaComponent(0.3), .clear]
gradientLayer.frame = self.bounds
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
gradientLayer.colors = gradationColor.map { $0.cgColor }
gradientLayer.locations = [0.0, 0.5, 1.0]
self.layer.addSublayer(gradientLayer)
let animation = CABasicAnimation(keyPath: "locations")
animation.fromValue = [-0.7, -0.5, 0.0]
animation.toValue = [1.0, 1.3, 1.7]
animation.repeatCount = .infinity
animation.duration = 1.5
animation.timingFunction = CAMediaTimingFunction(name: .easeIn)
gradientLayer.add(animation, forKey: animation.keyPath)
}
}
// 사용하는 쪽
self.sampleView.animateShimmer()
CABasicAnimation응용 - UIImageView 이동
- 이번엔 gradientLayer인스턴스를 따로 생성하지 않고, 이미 존재하는 UIImage 인스턴스를 위처럼 이동되게끔 설정
- 파란색 sampleView와 화살표 이미지인 imageView 준비
private lazy var sampleView: UIView = {
let view = UIView()
view.backgroundColor = .systemBlue
view.translatesAutoresizingMaskIntoConstraints = false
view.layer.cornerRadius = 27
view.layer.cornerCurve = .continuous
view.clipsToBounds = true
self.view.addSubview(view)
return view
}()
private lazy var imageView: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "right")
view.translatesAutoresizingMaskIntoConstraints = false
self.sampleView.addSubview(view)
return view
}()
- viewDidAppear에서 animate()를 사용
- 1초 딜레이를 주기 위해서 Timer 사용
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.animate()
let delay = 1.0
DispatchQueue.main.asyncAfter(deadline: .now() + self.duration) {
Timer.scheduledTimer(withTimeInterval: self.duration + delay, repeats: true) { timer in
self.animate()
}
}
}
- animate() 구현
- CABasicAnimation의 "position.x" 속성을 이용하여 imageView를 이동
private func animate() {
self.imageView.layer.removeAnimation(forKey: "myAnimation")
let animation = CABasicAnimation(keyPath: "position.x")
animation.fromValue = 0
animation.toValue = self.sampleView.bounds.width
animation.duration = self.duration
animation.repeatCount = 1
animation.timingFunction = CAMediaTimingFunction(name: .easeIn)
self.imageView.layer.add(animation, forKey: "myAnimation")
}
* 전체 코드: https://github.com/JK0369/ExShimmerAnimation
* 참고
https://stackoverflow.com/questions/13913101/cabasicanimation-keys
https://developer.apple.com/documentation/quartzcore/cabasicanimation
https://medium.com/theengineeringgecko/shimmer-animations-in-ios-4c720089eaec
'iOS 응용 (swift)' 카테고리의 다른 글
Comments