如何在iPhone-OS中终止正在运行的动画?

时间:2009-05-17 14:09:49

标签: iphone core-animation

我有一个“Cube”类,并且有一个方法-rotate。该方法将anchorPoint设置在左下角,然后将立方体旋转90度。之后,调用另一种方法,使立方体向后旋转-90度。这已经完成了指定停止选择器。顺便说一下:这没什么特别的。刚刚学习!

-rotate在触摸事件时被调用。但是现在,当立方体对象仍在旋转时,假设它当前处于33.943 ......,用户可能会在该动画结束之前再发一次触摸事件。

然后,此触摸事件将立即再次调用-rotate方法。会发生的是,转换重叠并且立方体图像完全伸展和变形。

因此,在新动画开始之前,当前正在运行的动画必须停止。

更新

在我开始动画之前,我打电话给你:

- (void)resetAnimation {
    self.layer.transform = CATransform3DIdentity; // reset the transform to the identity transform ("no rotation applied, please")
    [Cube setAnimationDelegate:nil];
    [Cube setAnimationDidStopSelector:NULL];
}

另外,我设置了[Cube setAnimationBeginsFromCurrentState:YES];我开始动画块的地方。

因此,当从外部输入动画时,它将如下所示: (注意,屏幕上有5个这个类的对象,可以踢到动画)

- (void)kickAnimation { // if that's called, the cube gets a kick to rotate
    self.layer.transform = CATransform3DIdentity;
    currentDegrees = 90; // just testing! it may also be negative
    NSString *animID = [NSString stringWithFormat:@"cube_%i",self.datasetID];
    if (currentDegrees > 0) {
        [self rotateRight:animID finished:0 context:self];
    } else if (currentDegrees < 0) {
        [self rotateLeft:animID finished:0 context:self];
    }
}

- (void)rotateRight:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
    // 1) here the anchorPoint is set to the lower right corner
    // 2) here the view's frame is repositioned so that the cube doesn't move visually after the anchorPoint changed
    [self rotateByDegrees:currentDegrees animationID:animationID];
}

- (void)rotateByDegrees:(CGFloat)degrees animationID:(NSString *)animationID {
    [Cube beginAnimations:animationID context:self];
    [Cube setAnimationDelegate:self];
    [Cube setAnimationDidStopSelector:@selector(rotateBack:finished:context:)];
    [Cube setAnimationDuration:2.1f];
    [Cube setAnimationBeginsFromCurrentState:YES];
    CATransform3D rotatedTransform = self.layer.transform;
    rotatedTransform = CATransform3DRotate(rotatedTransform, degrees * M_PI / 180.0, 0.0f, 0.0f, 1.0f);
    self.layer.transform = rotatedTransform;
    [UIView commitAnimations];
}

- (void)rotateBack:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
    currentDegrees *= -1;
    [Cube beginAnimations:animationID context:self];
    self.layer.transform = CATransform3DIdentity;
    [Cube setAnimationDelegate:nil];
    [Cube setAnimationDidStopSelector:NULL];
    [Cube setAnimationDuration:2.1f];
    [Cube setAnimationBeginsFromCurrentState:YES];
    CATransform3D rotatedTransform = self.layer.transform;
    rotatedTransform = CATransform3DRotate(rotatedTransform, currentDegrees * M_PI / 180.0, 0.0f, 0.0f, 1.0f);
    self.layer.transform = rotatedTransform;
    currentDegrees = 0;
    [UIView commitAnimations];
}

现在它几乎可以工作了。如果动画启动重叠,立方体不会再变形。但有一点是错误的:如果一个新的“踢”进来,并且立方体当前正在向后旋转,它应该立即开始向右旋转。但碰巧它首先旋转然后识别出“踢”,看起来很奇怪;)

3 个答案:

答案 0 :(得分:5)

Here是一个类似的问题和答案。

如果您致电[UIView setAnimationBeginsFromCurrentState:YES];,新动画将从视图所在位置开始,并停止上一个动画。

答案 1 :(得分:3)

如果您确实要停止所有动画,然后使用上述方法重新启动,请致电:

[self.layer removeAllAnimations];

答案 2 :(得分:2)

你是如何应用变换的?我正在想象这样的事情:

- (void)rotate {
    [UIView beginAnimations:@"rotate" context:nil];
    self.transform = [self nextTargetTransform];
    [UIView commitAnimations];
}

我没有为你的立方体示例编写代码,但这应该没有你看到的问题。 beginAnimations:context:应该认识到您已经在转换,并创建一个平滑完成转换的新目标状态。这不会发生吗?

像我说的那样,我没有测试过上面的内容;一个可能的打嗝是动画将突然跳回到原始设置并重新开始。如果发生这种情况,请发表评论和更多代码,我们将解决该问题。