728x90
이 애니메이션 효과를 뭐라고 표현해야할지 모르겠는데 주로 녹화같은 것 할 때 깜빡거리는 애니메이션 용도로 자주 봤던 것 같아서 Recording Wave View라고 했다.
Github: https://github.com/Sky-Titan/WaveViewExample
WaveView
import UIKit
class WaveView: UIView {
override class var layerClass: AnyClass {
WaveLayer.self
}
var waveLayer: WaveLayer? {
layer as? WaveLayer
}
@IBInspectable
var waveColor: UIColor? {
get {
waveLayer?.waveColor
}
set {
waveLayer?.waveColor = newValue
waveLayer?.setNeedsDisplay()
}
}
@IBInspectable
var circleColor: UIColor? {
get {
waveLayer?.circleColor
}
set {
waveLayer?.circleColor = newValue
waveLayer?.setNeedsDisplay()
}
}
@IBInspectable
var waveDuration: CGFloat {
get {
waveLayer?.waveDuration ?? 0.3
}
set {
waveLayer?.waveDuration = newValue
waveLayer?.outerLayer?.removeAllAnimations()
}
}
func startWave() {
waveLayer?.startWave()
}
func stopWave() {
waveLayer?.stopWave()
}
}
class WaveLayer: CALayer {
fileprivate var outerLayer: CAShapeLayer?
fileprivate var waveColor: UIColor?
fileprivate var circleColor: UIColor?
fileprivate var waveDuration: CGFloat = 0.3
override func draw(in ctx: CGContext) {
let radius: CGFloat = min(self.bounds.width / 2, self.bounds.height / 2)
let center: CGPoint = CGPoint(x: self.bounds.width / 2, y: self.bounds.height / 2)
self.removeAllSubLayers()
let outerLayer = makeCircleLayer(center, radius: radius, fillColor: waveColor?.cgColor)
addSublayer(outerLayer)
self.outerLayer = outerLayer
let innerLayer = makeCircleLayer(center, radius: radius, fillColor: circleColor?.cgColor)
addSublayer(innerLayer)
}
private func makeCircleLayer(_ center: CGPoint, radius: CGFloat, fillColor: CGColor?) -> CAShapeLayer {
let circleLayer = CAShapeLayer()
circleLayer.frame = self.bounds
circleLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
circleLayer.position = CGPoint(x: self.bounds.width / 2, y: self.bounds.height / 2)
circleLayer.path = UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: .pi * 2, clockwise: false).cgPath
circleLayer.fillColor = fillColor
return circleLayer
}
fileprivate func startWave() {
outerLayer?.removeAllAnimations()
let animation = CABasicAnimation(keyPath: "transform.scale")
animation.fromValue = 1
animation.toValue = 1.3
animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
animation.repeatCount = .infinity
animation.autoreverses = true
animation.duration = waveDuration
animation.beginTime = CACurrentMediaTime()
outerLayer?.add(animation, forKey: "wave")
}
fileprivate func stopWave() {
outerLayer?.removeAllAnimations()
}
}
extension CALayer {
func removeAllSubLayers() {
self.sublayers?.forEach({
$0.removeFromSuperlayer()
})
}
}
- innerLayer, outerLayer라고 하는 원형 subLayer 2개를 사용
- outerLayer에 scale 조절하는 easeInOut 타이밍의 애니메이션을 넣음으로써 wave 애니메이션을 표현한다.
728x90
'iOS > 예제' 카테고리의 다른 글
[iOS 예제] CircularCarouselBannerView (0) | 2022.08.19 |
---|---|
[iOS 예제] UICollectionView에서 cell 수직방향 정렬 (0) | 2022.08.06 |
[iOS 예제] Roulette 만들기 (0) | 2022.06.25 |
[iOS 예제] Ripple Effect (0) | 2022.06.19 |
[iOS 예제] CircleProgressView 만들기 (0) | 2021.12.11 |
댓글