2010-07-14 77 views
5

这一个已经被我发疯...强制CALayer的旋转方向?

考虑到“面”是一个CALayer的,我在X轴旋转它:

plane.transform = CATransform3DMakeRotation(180 * M_PI/180.0f, 1.0f, 0.0f, 0.0f); 

,这使得它顺时针旋转,这是完美的。

现在,在某个时间点,我想它返回到0度,所以我使用:

plane.transform = CATransform3DMakeRotation(0 * M_PI/180.0f, 1.0f, 0.0f, 0.0f); 

的事情是......它是反时针方向,这是不是我想要:(

我猜它使用最短的旋转路径,但即使我告诉它去360度,而当它完成,我告诉它重新开始动画,它从360开始去180,它向后而不是正确的方向。

有没有办法解决?

我会在的Actionscript做将是:

if (plane.rotationX == 360) plane.rotationX = 0; 

而且它会很好地恢复,但如果我这样做,是因为使用了动画的CATransform3DMakeRotation两个转变发生碰撞,(我认为),它会变得混乱。

任何帮助将不胜感激!

感谢

+0

我看到这是一个恶棍:( – Andre 2010-07-15 15:18:30

回答

8

这个问题出现时,我正在寻找解决类似的问题。我想旋转一个180度的图像,然后想要继续前进以获得完整的空翻。 iOS想要走最短的路线。这里的答案对我没有太大的帮助。我最终在keyPath动画中查找了一些内容,并解决了我的问题。以下是该方法的一个例子。

对于问题中提出的特定问题,您需要两组不同的keyFrameValues,一组用于初始旋转,另一组用于第二个。但通过输入一个中间值,您可以获得所需的效果,即采取更长的路径或强制选择同样长的路径,如果这是您想要的。我在评论中留下了一些变体代码,因为他们可能会帮助不熟悉CAKeyFrameAnimation的人遵循代码/了解各种选项。

- (void) somersault; 
{ 

    CALayer* layer = [self layer]; 
    NSMutableArray* keyFrameValues = [NSMutableArray array]; 
    [keyFrameValues addObject:[NSNumber numberWithFloat:0.0]]; 
    //[values addObject:[NSNumber numberWithFloat:M_PI*0.5]]; 
    [keyFrameValues addObject:[NSNumber numberWithFloat:M_PI]]; 
    [keyFrameValues addObject:[NSNumber numberWithFloat:M_PI*1.5]]; 
    [keyFrameValues addObject:[NSNumber numberWithFloat:M_PI*2.0]]; 

    CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; 
    [animation setValues:keyFrameValues]; 
    [animation setValueFunction:[CAValueFunction functionWithName: kCAValueFunctionRotateX]];// kCAValueFunctionRotateZ]]; 

    [animation setDuration:0.9]; 
    //[animation setTimingFunction: [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; 

    [layer addAnimation:animation forKey:nil]; 

    return; 
} 
+1

如果你想要一个稳定的动画,你可以设置'animation.calculationMode = kCAAnimationPaced',CoreAnimation将随着时间的推移均匀插入角度。 – kevboh 2011-12-07 16:03:50

1

我觉得你的问题是降低到期望有点太多了隐式动画系统,它基本上只是去从A插值图层属性值B.这为各种大的情况,但它不允许你按顺序一起做“连锁”变更等事情。有办法做后者,虽然他们肯定不如现在做的那么方便。不过,你可能想要调查那些“正确地”做事情。 (开始与另一看看Core Animation Guide

但是,如果你愿意忍受一个俗气的解决方法,你可能能够得到这个看你怎么想仅仅通过不断改变旋转在同一方向的角度每次而不是将其设置为常数0180:与我怎么会想到变换

// you need to keep track of this somewhere in your code 
// (I've made it static for simplicity, you should do something more sensible) 
static long currentAngle = 0; 

// rotate (another) 180 degrees 
currentAngle += 180; 
plane.transform = CATransform3DMakeRotation(currentAngle * M_PI/180.0f, 1.0f, 0.0f, 0.0f); 

我说“可能”,因为东西在你的描述并没有真正的磬去工作,而且显然有一些我不推崇的实施细节理解。这种方法可能会失败。但它非常简单,所以可能值得一试。

+0

谢谢您的帮助。不幸的是我已经试过了已经,只是它没有工作,因为我的飞机可以去两种方式,累积旋转被糟蹋了。作为这是我试图复制的内容:www.assalino.com(介绍之后的3D堆栈)我在AS3中做了它,它相对简单,关键是能够将旋转从-180改变为180(例如)没有动画,我发现在Core Animation中做的唯一方法是将duration属性更改为0,然后将其设置回最终动画,但它们重叠并且不起作用。 – Andre 2010-07-19 13:35:31

+0

@Andre你的Flash不适合我(真的,人生太短),所以也许我错过了一些东西,但我不知道如何他的双向飞机应该会影响累计轮换 - 如果它以一种方式运作,它应该可以在另一方面发挥作用。在任何情况下,如果这种黑客行不通,我认为你需要放弃隐式动画并使用明确的动画 - 你可以随意停止和启动这些动画,指定值序列和时间,完成时会收到通知, – walkytalky 2010-07-20 03:24:15

0

对我来说这样的解决方案。您可以添加一个中间旋转值以显示视图应旋转到哪个方向。所以你不需要CAKeyframeAnimation

if backwardDirection { 
    view.transform = CGAffineTransform(rotationAngle: -CGFloat.pi/2) 
    view.transform = CGAffineTransform(rotationAngle: 0) 
} else { 
    view.transform = CGAffineTransform(rotationAngle: -CGFloat.pi/2) 
    view.transform = CGAffineTransform(rotationAngle: -CGFloat.pi) 
}