【问题标题】:Pausing CALayer animation with an animation with a delay使用延迟动画暂停 CALayer 动画
【发布时间】:2012-04-06 00:13:28
【问题描述】:

我有一组嵌套的 UIView 动画(在给定时间有 2 或 3 层深),我希望能够暂停和恢复。其中一些动画使用-animateWithDuration:animations:completion:,而另一些使用-animateWithDuration:delay:options:animations:completion: 以延迟动画块的执行。

我阅读并实现了 Technical Q&A QA1673 关于暂停图层树中所有动画的内容,但我遇到了使用延迟参数的动画的问题。我可以很好地暂停和恢复动画,但是当动画恢复时,任何具有相关延迟的动画块似乎都将延迟延长了层树暂停的时间量。因此,例如,如果其中一个块有 1 秒的延迟,并且层树暂停了 3 秒,则动画在恢复后延迟 4 秒。我猜这与beginTime 属性有关?任何帮助将不胜感激。

// Pause and Resume methods, right from the technical Q&A
- (void)pauseAnimationsOnLayer:(CALayer *)layer
{
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
    layer.speed = 0.0;
    layer.timeOffset = pausedTime;
}

- (void)resumeAnimationsOnLayer:(CALayer *)layer
{
    CFTimeInterval pausedTime = [layer timeOffset];
    layer.speed = 1.0;
    layer.timeOffset = 0.0;
    layer.beginTime = 0;
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    layer.beginTime = timeSincePause;
}

// Chained animations
- (void)animateNextPopup
{
    [UIView animateWithDuration:kRFPVictorySequenceStatePopupDuration
                     animations:^{
                         [_currentStateImageView setHidden:NO];
                         [_currentStateImageView setTransform:CGAffineTransformIdentity];

                     }
                     completion:^(BOOL finished) {
                         [UIView animateWithDuration:kRFPVictorySequenceStateSlideOffDuration
                                               delay:kRFPVictorySequenceStateVoteDelay
                                             options:UIViewAnimationOptionCurveEaseInOut
                                          animations:^{
                                              if (winnerIsDem) {
                                                  [_currentStateImageView setFrame:CGRectMake(-_currentStateImageView.frame.size.width, 
                                                                                              _currentStateImageView.frame.origin.y, 
                                                                                              _currentStateImageView.frame.size.width, 
                                                                                              _currentStateImageView.frame.size.height)];
                                              }
                                              else {
                                                  [_currentStateImageView setFrame:CGRectMake(1024, 
                                                                                              _currentStateImageView.frame.origin.y, 
                                                                                              _currentStateImageView.frame.size.width, 
                                                                                              _currentStateImageView.frame.size.height)];
                                              }
                                          }
                                          completion:^(BOOL finished) {
                                              // Do some stuff
                                          }
                          ];
                     }
     ];
}

【问题讨论】:

    标签: ios objective-c uiview core-animation


    【解决方案1】:

    我建议一种不同的方法。

    动画块很容易实现,但只有在您不需要对动画进行任何控制时才有用。

    否则,您应该使用计时器并手动创建自己的动画。

    [NSTimer scheduledTimerWithTimeInterval:0.1
                                     target:self
                                   selector:@selector(timerFired)
                                   userInfo:nil
                                    repeats:YES];
    
    - (void)timerFired
    {
        if (isPaused) {
            // Do nothing
        } else {
            // Animate
        }
    }
    
    - (IBAction)pauseTapped:(id)sender
    {
        if (isPaused) {
            isPaused = NO;
        } else {
            isPaused = YES;
        }
    }
    

    isPaused 是一个控制动画状态的标志。

    【讨论】:

    • 感谢您的回复,但这个想法实际上也有其自身的问题。使用标准NSTimer 不会使动画与设备的显示速率同步,这会导致动画看起来不连贯。最好使用CADisplayLink,它类似但专门为与显示器同步而设计。尽管如此,使用一个显示链接对象来运行大约 10 个序列化动画可能会导致一些严重的意大利面条代码。最后,我的问题是为什么暂停层树中的动画会影响后续动画的延迟值?看起来很奇怪,不是吗?
    • “一些严肃的意大利面条代码”......是的,你是对的......但毕竟我是意大利人;)
    【解决方案2】:

    我找到了问题的解决方案!您必须在动画的完成块中将 self.layer.beginTime 值重置为零。

    例如

    [UIView animateWithDuration:element.duration 
                          delay:element.delay 
                        options:UIViewAnimationOptionCurveLinear
                     animations:^{
                          // Animate properties here!
                         }
                     } completion:^(BOOL finished){
                                  // Reset BeginTime all the time
                                  // So, in case a pause took place the delay values are valid again!
                             **self.layer.beginTime = 0.0f;**
                     }];
    

    暂停/恢复代码的其余部分保持不变。

    最好的!

    【讨论】:

    • 该死的,我希望这能奏效......但它对我来说不是 :(,它没有效果。现在我正在解决通过动画块消除延迟。跨度>
    • @cclogg 如果您在同一层上运行许多块动画,则必须设置一次,而不是在每个块动画中:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    • 2012-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多