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

Posted

技术标签:

【中文标题】如何在 iPhone-OS 中终止正在运行的动画?【英文标题】:How can I terminate a running animation in iPhone-OS? 【发布时间】:2009-05-17 14:09:48 【问题描述】:

我有一个类“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];

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

【问题讨论】:

【参考方案1】:

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

如果您调用[UIView setAnimationBeginsFromCurrentState:YES];,新动画将从视图所在的位置开始并停止之前的动画。

【讨论】:

【参考方案2】:

如果您真的想停止所有动画,然后使用上述方法重新启动,请调用:

[self.layer removeAllAnimations];

【讨论】:

【参考方案3】:

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

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

我还没有为您的多维数据集示例编写代码,但这应该可以在没有您看到的问题的情况下工作。 beginAnimations:context: 应该认识到您已经在转换,并创建一个新的目标状态以顺利完成转换。这没有发生吗?

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

【讨论】:

不,这似乎不会发生。我在代码中找到了一个可以将其设置为身份转换的点。我只是没有把它放在正确的地方。我有一种方法可以设置 anchorPoint 并在此之后纠正框架的移动,以便视图不会移动。这引起了问题。在我更改锚点之前,我现在设置了身份转换,它可以工作。虽然不完美。我用我设置转换的方式更新了上面的代码。 查看您的代码,我看到了一些东西。最重要的是,您将图层变换设置在一个位置,将视图变换设置在另一个位置。这些是不同的变换。你应该选择一个东西来改变并坚持下去。您还没有展示如何执行动画本身;你有 -beginAnimations: 在某处阻塞吗?通常你应该开始一个动画块,设置你当前的目标状态,然后提交动画。我可能会将目标保留在单独的模型变量中,而不是不断地重新转换转换,但两者都可以工作。 另外一件事:既然你在搞乱层,请注意modelLayer和presentationLayer之间的区别。一个是目标状态,另一个是当前屏幕上的内容(您在动画中的位置)。 谢谢罗伯。我用更多代码更新了我的帖子。我尝试设置 self.layer.transform = CGAffineTransformIdentity,但这仅适用于 self.transform。但我现在发现我可以做 self.layer.transform = CATransform3DIdentity。那么你会建议在 self.layer.transform 而不是 self.transform 上制作动画吗?当我在模型变量中捕获目标状态时,它会是什么样子? “目标状态”究竟是什么? 对于 3D 动画,您希望转换图层而不是视图。 CALayer 有比 UIView 更强大的变换和动画。你应该阅读核心动画编程指南:developer.apple.com/iphone/library/documentation/Cocoa/…。我对“目标”状态的使用有点不标准;我的意思是,在 CA 中,您设置一个属性(您的“目标”),然后 CA 完成所有工作以实现目标。如果你改变它,你通常不必担心你在哪里。 CA 将重新计算通往新目标的路径。

以上是关于如何在 iPhone-OS 中终止正在运行的动画?的主要内容,如果未能解决你的问题,请参考以下文章

如何终止正在运行的 DolphinDB 查询

如何在不终止正在运行的 jar 文件进程的情况下关闭终端 [重复]

如何从 Corda 的 CordApp 中超时/终止正在运行的流程

linux中怎么终止正在运行的进程

如何正确的终止正在运行的子线程

Java中终止正在运行线程