SpringWithDamping для анимаций CALayer?
После многого с динамическими анимациями UIView
, представленными в iOS 7, наиболее заметно:
[UIView animateWithDuration: delay: usingSpringWithDamping: initialSpringVelocity: options: animations: completion:];
Мне было интересно, есть ли эквивалент метода SpringWithDamping/Velocity, к которому можно получить доступ непосредственно при создании анимации CALayer
? То есть либо через CATransaction
, CABasicAnimation
или иначе...
Спасибо
Ответы
Ответ 1
в iOS9 Яблоко наконец объявило класс CASpringAnimation
общедоступным.
Вы можете использовать его так:
let spring = CASpringAnimation(keyPath: "position.x")
spring.damping = 5
spring.fromValue = myLayer.position.x
spring.toValue = myLayer.position.x + 100.0
spring.duration = spring.settlingDuration
myLayer.addAnimation(spring, forKey: nil)
Обратите внимание, что вы не можете установить продолжительность анимации - вам нужно задать класс CASpringAnimation
для settlingDuration
(например, "Сколько времени потребуется для установки системы spring" ), а затем установите это как продолжительность вашей анимации.
Проверьте файлы заголовков для CASpringAnimation
- он предоставляет несколько системных переменных spring, которые вы можете настроить - жесткость, масса и т.д.
Ответ 2
Есть (и на некоторое время) закрытый класс под названием CASpringAnimation
, который, я уверен, используется за всем этим (но я рад это проверено). К сожалению, он по-прежнему частный.
Ответ 3
Как сказал Дэвид, CASpringAnimation
является приватным (на данный момент?), но недавно я встретил RBBSpringAnimation
из RBBAnimation проект.
Я могу определенно рекомендовать это, было очень легко зайти в качестве замены для моего существующего CABasicAnimation.
Ответ 4
Я написал класс для создания экземпляра CASpringAnimation
. Он работает довольно простым способом:
Создав анимацию spring из UIKit API, она арестовывает созданный экземпляр CASpringAnimation
с уровня представления, копирует его и возвращает.
Но я не знаю, безопасно ли это в App Store, чтобы создать CASpringAnimation
таким образом.
import UIKit
private let SharedCASpringAnimationFactory = CASpringAnimationFactory()
public class CASpringAnimationFactory {
private var dummyView: UIView
private init() {
dummyView = UIView(frame: CGRect.zeroRect)
}
private class var shared: CASpringAnimationFactory {
return SharedCASpringAnimationFactory
}
public class func animation(#keyPath: String, dumping: CGFloat, initialSpringVelocity: CGFloat) -> CABasicAnimation {
let duration = CATransaction.animationDuration()
UIView.animateWithDuration(duration, delay: 0.0, usingSpringWithDamping: dumping, initialSpringVelocity: initialSpringVelocity, options: nil,
animations: { () -> Void in
CASpringAnimationFactory.shared.dummyView.bounds = CGRect(origin: CGPoint.zero, size: CGSize(width: 100, height: 100))
}, completion: nil)
let dummyLayer = CASpringAnimationFactory.shared.dummyView.layer
let animations = dummyLayer.animationKeys().map {dummyLayer.animationForKey($0 as String) as CAAnimation}
let arrestedAnimation = animations.first!.copy() as CABasicAnimation
arrestedAnimation.keyPath = keyPath
arrestedAnimation.fromValue = nil
arrestedAnimation.toValue = nil
dummyLayer.removeAllAnimations()
shared.dummyView.bounds = CGRect.zeroRect
return arrestedAnimation
}
}