Ключевая проблема заключается в том, что ваша анимация запускается со смещенными задержками в диапазоне от 0,1 до 1,0 секунды. Пока не начнется последняя анимация, этот слой просто сидит там, в натуральную величину и с непрозрачностью 100%.
Поскольку вы анимируете масштаб преобразования от 0 до 1, я бы предложил установить начальное преобразование на 0 ( или изменив opacity
на 0). Тогда вы не увидите их сидящими там, пока не начнутся соответствующие анимации.
Несколько других наблюдений:
draw(_:)
не подходящее место для добавления слоев , запустить анимацию и т. д. c. Этот метод может вызываться несколько раз и должен представлять представление в данный момент времени. Я бы ушел на пенсию draw(_:)
, если это не то место, чтобы начать это, и вам вообще не нужен этот метод.
Вы запускаете свою первую анимацию через 0,1 секунды. Почему бы не запустить его немедленно?
Корректировки фрейма следует обрабатывать, откладывая настройку свойств path
и position
до layoutSubviews
.
Таким образом:
@IBDesignable
class AnimatedCircleView: UIView {
private var animatedLayers = [CAShapeLayer]()
override init(frame: CGRect = .zero) {
super.init(frame: frame)
configure()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
configure()
}
override func layoutSubviews() {
super.layoutSubviews()
let path = UIBezierPath(arcCenter: .zero, radius: bounds.width / 2.3, startAngle: 0, endAngle: 2 * .pi, clockwise: true)
for animatedLayer in animatedLayers {
animatedLayer.path = path.cgPath
animatedLayer.position = CGPoint(x: bounds.midX, y: bounds.midY)
}
}
}
// MARK: - Methods
private extension AnimatedCircleView {
func configure() {
for _ in 0...3 {
let animatedLayer = CAShapeLayer()
animatedLayer.strokeColor = UIColor.black.cgColor
animatedLayer.lineWidth = 0
animatedLayer.fillColor = UIColor.gray.cgColor
animatedLayer.lineCap = .round
animatedLayer.transform = CATransform3DMakeScale(0, 0, 1)
layer.addSublayer(animatedLayer)
animatedLayers.append(animatedLayer)
}
self.animateCircle(index: 0)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.animateCircle(index: 1)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
self.animateCircle(index: 2)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.animateCircle(index: 3)
}
}
}
}
func animateCircle(index: Int) {
let scaleAnimation = CABasicAnimation(keyPath: "transform.scale")
scaleAnimation.duration = 1.8
scaleAnimation.fromValue = 0
scaleAnimation.toValue = 1
scaleAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
scaleAnimation.repeatCount = .greatestFiniteMagnitude
animatedLayers[index].add(scaleAnimation, forKey: "scale")
let opacityAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.opacity))
opacityAnimation.duration = 1.8
opacityAnimation.fromValue = 0.7
opacityAnimation.toValue = 0
opacityAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
opacityAnimation.repeatCount = .greatestFiniteMagnitude
animatedLayers[index].add(opacityAnimation, forKey: "opacity")
}
}