Есть ли способ приостановить CABasicAnimation?
У меня есть базовая анимация вращения iPhone. Есть ли способ, которым я могу "приостановить" анимацию, чтобы сохранить положение вида? Я думаю, что один из способов сделать это - заставить анимацию завершиться, вместо того, чтобы вызывать "удалить", как бы я это сделал?
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2];
rotationAnimation.duration = 100;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = HUGE_VALF;
rotationAnimation.removedOnCompletion = NO;
rotationAnimation.fillMode = kCAFillModeForwards;
[myView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
5 ответов
Недавно появившаяся техническая заметка Apple QA1673 описывает, как приостановить / возобновить анимацию слоя.
Список приостановки и возобновления анимации приведен ниже:
-(void)pauseLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;
}
-(void)resumeLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}
Редактирование: iOS 10 представила новый API - UIViewPropertyAnimator, который позволяет обрабатывать анимации более интерактивно, например, позволяет легко приостанавливать и возобновлять анимацию или "искать" ее для определенного значения прогресса.
Ответ для Свифта 3:
Кредиты @Vladimir
Код:
func pauseAnimation(){
var pausedTime = layer.convertTime(CACurrentMediaTime(), fromLayer: nil)
layer.speed = 0.0
layer.timeOffset = pausedTime
}
func resumeAnimation(){
var pausedTime = layer.timeOffset
layer.speed = 1.0
layer.timeOffset = 0.0
layer.beginTime = 0.0
let timeSincePause = layer.convertTime(CACurrentMediaTime(), fromLayer: nil) - pausedTime
layer.beginTime = timeSincePause
}
Установите текущее состояние слоя вашего представления, чтобы соответствовать состоянию presentationLayer
затем удалите анимацию:
CALayer *pLayer = [myView.layer presentationLayer];
myView.layer.transform = pLayer.transform;
[myView.layer removeAnimationForKey:@"rotationAnimation"];
Кредит @Vladimir и @ Supratik-Majumdar
Swift 5.1 как расширение CALayer
extension CALayer
{
func pauseAnimation() {
if isPaused() == false {
let pausedTime = convertTime(CACurrentMediaTime(), from: nil)
speed = 0.0
timeOffset = pausedTime
}
}
func resumeAnimation() {
if isPaused() {
let pausedTime = timeOffset
speed = 1.0
timeOffset = 0.0
beginTime = 0.0
let timeSincePause = convertTime(CACurrentMediaTime(), from: nil) - pausedTime
beginTime = timeSincePause
}
}
func isPaused() -> Bool {
return speed == 0
}
}
Вы можете использовать таймер или обработать метод делегата анимации:
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
Вот мой код:
// ...
[self startAnimation];
// ...
- (void)startAnimation {
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.fromValue = [NSNumber numberWithFloat:0];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_2_PI];
rotationAnimation.duration = 1.0;
rotationAnimation.cumulative = YES;
// rotationAnimation.repeatCount = 0; // <- if repeatCount set to infinite, we'll not receive the animationDidStop notification when the animation is repeating
rotationAnimation.removedOnCompletion = NO;
rotationAnimation.fillMode = kCAFillModeForwards;
rotationAnimation.delegate = self; // <- hanlde the animationDidStop method
[myView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
if (shouldContinueAnimation) // <- set a flag to start/stop the animation
[self startAnimation];
}
Надеюсь, это поможет вам.
Самый простой
self.viewBall.layer.position = self.viewBall.layer.presentationLayer().position