坚持使用XCode动画链

时间:2010-06-29 21:52:10

标签: xcode rotation core-animation

我正在尝试做一个非常简单的动画,但它给了我很多的悲伤......我必须做一些简单的事情,并且错过了一点我想要的结果。

发布在此处:Rotating around a diagonal axis

我试图重新制作一个“黑白棋”片 - 一个正在激活的方块会围绕轴Y = X旋转,并改变颜色以产生旋转以显示其背面的错觉。所以,一边是蓝色,另一边是红色。

为了完成这项工作,我不得不将动画分成4个部分: 1)绕Y = X旋转90度 2)将颜色从oldColor更改为0.5 * oldColor(给出调暗的错觉) 3)绕Y = X旋转90度(将“后”侧面朝前面) 4)将颜色从0.5 * newColor更改为newColor(当照片更多地进入光线时,会产生照明幻觉)

理论上这很好......问题是,前两个步骤执行得非常好,但我无法解决后两个问题。

我尝试在CAAnimationGroup中进行操作,但问题是,我需要明确地将颜色设置为新颜色,否则当步骤3和4动画开始时,闪烁为原始颜色。我无法弄清楚如何在组中做到这一点,所以我将它们分解为单独的动画,并将它们链接起来如下: 1)火1& 2 2)抓住animationDidStop:finished:事件并设置颜色,然后触发3& 4

这样做,3& 4永远不会开火。它只是挂起。

所以我尝试将3& 4上的timeOffset更改为1& 2动画的持续时间。这导致1& 2没有开火,但3& 4工作得很漂亮...... ARG!

Here is the code broken out as individual animations:
<pre><code>
- (IBAction)handleButtonClick {
 FlipLayer3View *v = (FlipLayer3View *)[self view];
 col = ctr % 2 ? [UIColor blueColor].CGColor : [UIColor redColor].CGColor;

 [self aniFromColor:v.theSquare.backgroundColor toColor:col];

 ctr++;
}

- (void)aniFromColor:(CGColorRef)fromCol toColor:(CGColorRef)toCol {
 FlipLayer3View *v = (FlipLayer3View *)[self view];
 const CGFloat *fromColors = CGColorGetComponents(fromCol);
 const CGFloat *toColors = CGColorGetComponents(toCol);

 v.theSquare.backgroundColor = fromCol;

 ani1 = [[CABasicAnimation animationWithKeyPath:@"transform"] retain];
 [ani1 setDuration:dur];
 [ani1 setToValue:[NSValue valueWithCATransform3D:CATransform3DConcat(v.theSquare.transform, CATransform3DRotate(CATransform3DIdentity, M_PI/2, -1, 1, 0))]];
 [ani1 setValue:@"shrink" forKey:@"name"];
 [ani1 setDelegate:self];
 [ani1 setFillMode:kCAFillModeForwards];
 [ani1 setRemovedOnCompletion:NO];

 ani2 = [[CABasicAnimation animationWithKeyPath:@"backgroundColor"] retain];
 UIColor *c1 = [UIColor colorWithRed:(fromColors[0]/2.0f) green:(fromColors[1]/2.0f) blue:(fromColors[2]/2.0f) alpha:1.0f];

 const float *cgCol1 = CGColorGetComponents(fromCol);
 const float *cgCol2 = CGColorGetComponents(c1.CGColor);
 NSLog(@"Setting color FROM R:%f G:%f B:%f", cgCol1[0], cgCol1[1], cgCol1[2]);
 NSLog(@"Setting color TO R:%f G:%f B:%f", cgCol2[0], cgCol2[1], cgCol2[2]);

 [ani2 setDuration:dur];
 [ani2 setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
 [ani2 setFromValue:(id)fromCol];
 [ani2 setToValue:(id)c1.CGColor];
 [ani2 setValue:@"dim" forKey:@"name"];
 [ani2 setDelegate:self];
 [ani2 setFillMode:kCAFillModeForwards];
 [ani2 setRemovedOnCompletion:NO];

 ani3 = [[CABasicAnimation animationWithKeyPath:@"transform"] retain];
 [ani3 setDuration:dur];
 [ani3 setFromValue:[NSValue valueWithCATransform3D:CATransform3DConcat(v.theSquare.transform, CATransform3DRotate(CATransform3DIdentity, M_PI/2, -1, 1, 0))]];
 [ani3 setToValue:[NSValue valueWithCATransform3D:v.theSquare.transform]];
 [ani3 setValue:@"grow" forKey:@"name"];
 [ani3 setTimeOffset:dur];
 [ani3 setDelegate:self];
 [ani3 setFillMode:kCAFillModeForwards];
 [ani3 setRemovedOnCompletion:NO];

 ani4 = [[CABasicAnimation animationWithKeyPath:@"backgroundColor"] retain];
 UIColor *c2 = [UIColor colorWithRed:(toColors[0]/2.0f) green:(toColors[1]/2.0f) blue:(toColors[2]/2.0f) alpha:1.0f];

 cgCol1 = CGColorGetComponents(c2.CGColor);
 cgCol2 = CGColorGetComponents(toCol);
 NSLog(@"Setting color FROM R:%f G:%f B:%f", cgCol1[0], cgCol1[1], cgCol1[2]);
 NSLog(@"Setting color TO R:%f G:%f B:%f", cgCol2[0], cgCol2[1], cgCol2[2]);

 [ani4 setDuration:dur];
 [ani4 setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
 [ani4 setFromValue:(id)c2.CGColor];
 [ani4 setToValue:(id)toCol];
 [ani4 setValue:@"glow" forKey:@"name"];
 [ani4 setTimeOffset:dur];
 [ani4 setDelegate:self];
 [ani4 setFillMode:kCAFillModeForwards];
 [ani4 setRemovedOnCompletion:NO];

 [v.theSquare addAnimation:ani1 forKey:@"rotate1"];
 [v.theSquare addAnimation:ani2 forKey:@"fadeout"];
 [v.theSquare addAnimation:ani3 forKey:@"rotate2"];
 [v.theSquare addAnimation:ani4 forKey:@"fadein"];
}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
 if (flag) {
  NSString *str = [anim valueForKey:@"name"];

  if ([str isEqual:@"shrink"]) {
   NSLog(@"SHRINK complete...");
  }
  else if ([str isEqual:@"dim"]) {
   NSLog(@"DIM complete...");

   FlipLayer3View *theView = (FlipLayer3View *)[self view];
   theView.theSquare.backgroundColor = col;
  }
  else if ([str isEqual:@"grow"]) {
   NSLog(@"GROW complete...");
  }
  else if ([str isEqual:@"glow"]) {
   NSLog(@"GLOW complete...");
  }
 }
}
</code></pre>

这里,FWIW是我在CAAnimationGroup解决方案中使用的代码:

<pre><code>
- (IBAction)handleButtonClick {
 FlipLayer3View *v = (FlipLayer3View *)[self view];
 CGColorRef c = ctr % 2 ? [UIColor redColor].CGColor : [UIColor blueColor].CGColor;

 aniGroup = [self aniFromColor:v.theSquare.backgroundColor toColor:c];

 [v.theSquare addAnimation:aniGroup forKey:@"rotate"];
 ctr++;
}

- (CAAnimationGroup *)aniFromColor:(CGColorRef)fromCol toColor:(CGColorRef)toCol {
 FlipLayer3View *v = (FlipLayer3View *)[self view];
 const CGFloat *fromColors = CGColorGetComponents(fromCol);
 const CGFloat *toColors = CGColorGetComponents(toCol);

 ani1 = [CABasicAnimation animationWithKeyPath:@"transform"];
 [ani1 setDuration:dur];
 [ani1 setToValue:[NSValue valueWithCATransform3D:CATransform3DConcat(v.theSquare.transform, CATransform3DRotate(CATransform3DIdentity, M_PI/2, -1, 1, 0))]];
 [ani1 setValue:@"shrink" forKey:@"name"];

 ani2 = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
 UIColor *c1 = [UIColor colorWithRed:(fromColors[0]/2.0f) green:(fromColors[1]/2.0f) blue:(fromColors[2]/2.0f) alpha:1.0f];
 [ani2 setDuration:dur];
 [ani2 setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
 [ani2 setToValue:(id)c1.CGColor];
 [ani2 setValue:@"dim" forKey:@"name"];

 ani3 = [CABasicAnimation animationWithKeyPath:@"transform"];
 [ani3 setDuration:dur];
 [ani3 setFromValue:[NSValue valueWithCATransform3D:CATransform3DConcat(v.theSquare.transform, CATransform3DRotate(CATransform3DIdentity, M_PI/2, -1, 1, 0))]];
 [ani3 setToValue:[NSValue valueWithCATransform3D:v.theSquare.transform]];
 [ani3 setValue:@"grow" forKey:@"name"];
 [ani3 setBeginTime:dur];

 ani4 = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
 UIColor *c2 = [UIColor colorWithRed:(toColors[0]/2.0f) green:(toColors[1]/2.0f) blue:(toColors[2]/2.0f) alpha:1.0f];
 [ani4 setDuration:dur];
 [ani4 setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
 [ani4 setFromValue:(id)c2.CGColor];
 [ani4 setToValue:(id)toCol];
 [ani4 setValue:@"glow" forKey:@"name"];
 [ani4 setBeginTime:dur];

 aniGroup = [CAAnimationGroup animation];
 [aniGroup setDuration:dur*2];
 [aniGroup setAnimations:[NSArray arrayWithObjects:ani1, ani2, ani3, ani4, nil]];
 [aniGroup setFillMode:kCAFillModeForwards];
 [aniGroup setRemovedOnCompletion:NO];

 return aniGroup;
}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
 if (flag) {
  NSString *str = [anim valueForKey:@"name"];

  if ([str isEqual:@"shrink"]) {
   NSLog(@"SHRINK complete...");
  }
  else if ([str isEqual:@"dim"]) {
   NSLog(@"DIM complete...");
  }
  else if ([str isEqual:@"grow"]) {
   NSLog(@"GROW complete...");
  }
  else if ([str isEqual:@"glow"]) {
   NSLog(@"GLOW complete...");
  }
 }
}
</code></pre>

有人请告诉我,我错过了什么样的傻瓜......这就是杀了我!

谢谢!

克里斯

1 个答案:

答案 0 :(得分:2)

好的,所以让我成为第一个称我为白痴的人......在我首先尝试的Group版本中,我有一个beginTime设置,但是当我转换为单个动画时,一定不能删除它,导致动画序列的后半部分失败。这让我尝试设置timeOffset,这给出了一个奇怪的结果,即没有触发前半部分,但是触发了第二部分。

我刚进去并删除了所有这些,beginTime,timeOffset等。然后解雇了前两个动画。然后在animationDidStop:finished:方法中,我改变动画层的颜色以避免闪回到原始颜色,最后启动第二组动画。 Et Viola !!!

供参考,以下是工作代码:


- (IBAction)handleButtonClick {
    FlipLayer3View *v = (FlipLayer3View *)[self view];
    col = ctr % 2 ? [UIColor blueColor].CGColor : [UIColor redColor].CGColor;

    [self aniFromColor:v.theSquare.backgroundColor toColor:col];

    ctr++;
}

- (void)aniFromColor:(CGColorRef)fromCol toColor:(CGColorRef)toCol {
    FlipLayer3View *v = (FlipLayer3View *)[self view];
    const CGFloat *fromColors = CGColorGetComponents(fromCol);
    const CGFloat *toColors = CGColorGetComponents(toCol);

    v.theSquare.backgroundColor = fromCol;

    ani1 = [[CABasicAnimation animationWithKeyPath:@"transform"] retain];
    [ani1 setDuration:dur];
    [ani1 setToValue:[NSValue valueWithCATransform3D:CATransform3DConcat(v.theSquare.transform, CATransform3DRotate(CATransform3DIdentity, M_PI/2, -1, 1, 0))]];
    [ani1 setValue:@"shrink" forKey:@"name"];
    [ani1 setDelegate:self];
    [ani1 setFillMode:kCAFillModeForwards];
    [ani1 setRemovedOnCompletion:NO];

    ani2 = [[CABasicAnimation animationWithKeyPath:@"backgroundColor"] retain];
    UIColor *c1 = [UIColor colorWithRed:(fromColors[0]/2.0f) green:(fromColors[1]/2.0f) blue:(fromColors[2]/2.0f) alpha:1.0f];

    const float *cgCol1 = CGColorGetComponents(fromCol);
    const float *cgCol2 = CGColorGetComponents(c1.CGColor);
    NSLog(@"Setting color FROM R:%f G:%f B:%f", cgCol1[0], cgCol1[1], cgCol1[2]);
    NSLog(@"Setting color TO R:%f G:%f B:%f", cgCol2[0], cgCol2[1], cgCol2[2]);

    [ani2 setDuration:dur];
    [ani2 setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
    [ani2 setFromValue:(id)fromCol];
    [ani2 setToValue:(id)c1.CGColor];
    [ani2 setValue:@"dim" forKey:@"name"];
    [ani2 setDelegate:self];
    [ani2 setFillMode:kCAFillModeForwards];
    [ani2 setRemovedOnCompletion:NO];

    ani3 = [[CABasicAnimation animationWithKeyPath:@"transform"] retain];
    [ani3 setDuration:dur];
    [ani3 setFromValue:[NSValue valueWithCATransform3D:CATransform3DConcat(v.theSquare.transform, CATransform3DRotate(CATransform3DIdentity, M_PI/2, -1, 1, 0))]];
    [ani3 setToValue:[NSValue valueWithCATransform3D:v.theSquare.transform]];
    [ani3 setValue:@"grow" forKey:@"name"]; [ani3 setDelegate:self];
    [ani3 setFillMode:kCAFillModeForwards];
    [ani3 setRemovedOnCompletion:NO];

    ani4 = [[CABasicAnimation animationWithKeyPath:@"backgroundColor"] retain];
    UIColor *c2 = [UIColor colorWithRed:(toColors[0]/2.0f) green:(toColors[1]/2.0f) blue:(toColors[2]/2.0f) alpha:1.0f];

    cgCol1 = CGColorGetComponents(c2.CGColor);
    cgCol2 = CGColorGetComponents(toCol);
    NSLog(@"Setting color FROM R:%f G:%f B:%f", cgCol1[0], cgCol1[1], cgCol1[2]);
    NSLog(@"Setting color TO R:%f G:%f B:%f", cgCol2[0], cgCol2[1], cgCol2[2]);

    [ani4 setDuration:dur];
    [ani4 setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
    [ani4 setFromValue:(id)c2.CGColor];
    [ani4 setToValue:(id)toCol];
    [ani4 setValue:@"glow" forKey:@"name"]; [ani4 setDelegate:self];
    [ani4 setFillMode:kCAFillModeForwards];
    [ani4 setRemovedOnCompletion:NO];

    [v.theSquare addAnimation:ani1 forKey:@"rotate1"];
    [v.theSquare addAnimation:ani2 forKey:@"fadeout"];

}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    if (flag) {
        NSString *str = [anim valueForKey:@"name"];

        if ([str isEqual:@"shrink"]) {
            NSLog(@"SHRINK complete...");
        }
        else if ([str isEqual:@"dim"]) {
            NSLog(@"DIM complete...");

            FlipLayer3View *theView = (FlipLayer3View *)[self view];
            theView.theSquare.backgroundColor = col;
            [theView.theSquare addAnimation:ani3 forKey:@"rotate2"];
            [theView.theSquare addAnimation:ani4 forKey:@"fadein"];
        }
        else if ([str isEqual:@"grow"]) {
            NSLog(@"GROW complete...");
        }
        else if ([str isEqual:@"glow"]) {
            NSLog(@"GLOW complete...");
        }
    }
}

如果有人看到问题或知道更好的方式,我很乐意听到!!

谢谢,

克里斯