2010-09-26 46 views
2

我正在与一些核心动画的第一次,并在实施一个纸牌,我可以翻转的过程中,我决定使用CALayer显示内容(不知道我怎么'我会得到双方,但这是另一个问题),我需要能够翻转它,移动它等...如何使CATransform3dMakeRotation以另一种方式旋转?并链接在一起

我使用CATransaction一些成功 - 在下面的代码片段中,卡片从左下角移动到左上角并翻转。问题是我不想翻转相反的方式,但不知道该怎么说,“嘿,你走错路了!”


[CATransaction begin]; 
[CATransaction setValue:[NSNumber numberWithFloat:2.0f] forKey:kCATransactionAnimationDuration]; 
myCard.position = CGPointMake(CGRectGetMidX(self.bounds)/2,CGRectGetMidY(self.bounds)/2); 
myCard.transform = CATransform3DMakeRotation(M_PI, 1, 0, 0); 
[CATransaction commit]; 

第二个问题是:我怎么才能得到它同时做两个转换?我尝试过嵌套两个CATransactions,但第二个刚好覆盖第一个。我也尝试将旋转矢量更改为2D,就像说绕x轴和y轴旋转一样,但这不等于只是围绕两个单独的轴翻转它。这是嵌套的代码。


[CATransaction begin]; 
[CATransaction setValue:[NSNumber numberWithFloat:2.0f] forKey:kCATransactionAnimationDuration]; 
myCard.position = CGPointMake(CGRectGetMidX(self.bounds)/2,CGRectGetMidY(self.bounds)/2); 
myCard.transform = CATransform3DMakeRotation(M_PI, 1, 0, 0); // rotate about x 

    [CATransaction begin]; 
    [CATransaction setValue:[NSNumber numberWithFloat:1.0f] forKey:kCATransactionAnimationDuration]; 
    myCard.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0); // rotate about y 
    [CATransaction commit]; 

[CATransaction commit]; 

这里,它是UIView动画块内部...我已经添加滑块的角度,X,Y,Z的旋转向量和t为时间。翻译发生在时间上= 2t,并且每个旋转应该都只需要t。

[CATransaction begin]; 
[CATransaction setValue:[NSNumber numberWithFloat:t * 2] forKey:kCATransactionAnimationDuration]; 
myCard.position = CGPointMake(CGRectGetMidX(self.view.bounds)/2,CGRectGetMidY(self.view.bounds)/2); 

    [UIView beginAnimations:nil context:nil]; 
    [UIView setAnimationDuration:t]; 
    myCard.transform = CATransform3DMakeRotation(angle, x, y, z); 
    [UIView commitAnimations]; 

    [UIView beginAnimations:nil context:nil]; 
    [UIView setAnimationDuration:t]; 
    [UIView setAnimationDelay:t]; 
    myCard.transform = CATransform3DMakeRotation(angle * 2, x, y, z); 
    [UIView commitAnimations]; 

[CATransaction commit]; 

这就是我现在所在:它所有的作品有一个例外。当卡达到pi/2和3 * pi/2时,y旋转反转(开始以相反的方向旋转)。它也在这些点上绕x轴翻转。但是x和z很好。很近!

CGMutablePathRef thePath = CGPathCreateMutable(); 
CGPathMoveToPoint(thePath,NULL,CGRectGetMidX(self.view.bounds)/2,CGRectGetMidY(self.view.bounds)/2*3); 
CGPathAddCurveToPoint(thePath,NULL, 
         CGRectGetMidX(self.view.bounds)/2,CGRectGetMidY(self.view.bounds)/2*2, 
         CGRectGetMidX(self.view.bounds)/2,CGRectGetMidY(self.view.bounds)/2*1.5, 
         CGRectGetMidX(self.view.bounds)/2,CGRectGetMidY(self.view.bounds)/2); 
CAKeyframeAnimation *moveAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"]; 
moveAnimation.path=thePath; 
CFRelease(thePath); 

CABasicAnimation *xRotation; 
xRotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"]; 
xRotation.fromValue = [NSNumber numberWithFloat:0.0]; 
xRotation.toValue = [NSNumber numberWithFloat:x * angle * M_PI]; 

CABasicAnimation *yRotation; 
yRotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"]; 
yRotation.fromValue = [NSNumber numberWithFloat:0.0]; 
yRotation.toValue = [NSNumber numberWithFloat:y * angle * M_PI]; 

CABasicAnimation *zRotation; 
zRotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; 
zRotation.fromValue = [NSNumber numberWithFloat:0.0]; 
zRotation.toValue = [NSNumber numberWithFloat:z * angle * M_PI]; 

CAAnimationGroup *groupAnimation = [CAAnimationGroup animation]; 
groupAnimation.duration = t; 
groupAnimation.removedOnCompletion = NO; 
groupAnimation.fillMode = kCAFillModeForwards; 
groupAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
groupAnimation.animations = [NSArray arrayWithObjects:moveAnimation, xRotation, yRotation, zRotation, nil]; 

[myCard addAnimation:groupAnimation forKey:@"animateCard"]; 

回答

9

我相信你在这种情况下,想要的是使用的keyPath喜欢this answer描述了帮手:

CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"]; 
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI]; 
rotationAnimation.duration = duration; 
[myCard.layer addAnimation:rotationAnimation forKey:@"rotationAnimation1"]; 

应转动关于动画第一阶段的X轴。对于第二,我相信如果你使用以下

CABasicAnimation *rotationAnimation2 = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"]; 
rotationAnimation2.toValue = [NSNumber numberWithFloat: M_PI]; 
rotationAnimation2.duration = duration2; 
rotationAnimation2.cumulative = YES; 
[myCard.layer addAnimation:rotationAnimation2 forKey:@"rotationAnimation2"]; 

它应该使动画累积,并可能产生所需的效果。我没有尝试过这个,所以可能需要一些修补,以获得您需要的确切结果。

当您直接使用变换时,Core Animation将插值从当前值到指定变换的变换。它会找到到达该变换的最短路径,这将限制动画方向。如果您尝试对相同的转换属性进行两次动画处理,则第二个值将仅覆盖第一个值,而不会将两个转换组合在一起。

但是,当使用这样的辅助键盘路径时,Core Animation将在您的开始角度和结束角度之间进行插值,因此您可以通过更改结束角度的符号来反转方向。它优化了角度值的变化,而不是底层变换的变化。您还应该能够将关键路径上的动画组合起来,因为对于每个键路径操作组合而言,都会为您生成变换。

+0

谢谢布拉德。我找到了一个类似的答案(不知道是哪个 - 我现在在工作......),它使用了CAKeyframeAnimation,并有旋转的中间值,这样可以保证动画通过所有关键值。它可以工作,并且可以通过设置开始和结束的方式绕着所有坐标轴旋转我的卡片,就像你想象的那样,中间停止一半。实际上,它适用于x和z,但是对于y,例如在2 * M_PI ,当它到达M_PI时,它会翻转并做另一次旋转,我认为这可能是同样的事情,我需要更多的点 – Steve 2010-09-27 16:37:57

+0

哦,我不能让它留在它结束的地方,我记得'CA'从WWDC视频中解决这个问题的人,但不记得如何去做请注意,是否可以执行'CATransaction'并将“myCard”的变换设置回标识以删除任何剩余的变换? (假设我可以让他们坚持!) – Steve 2010-09-27 16:39:59

+0

编辑:在我的第一个评论中,我错了(刚刚用我的手机上的应用程序)。它在y旋转通过M_PI/2,M_PI和3 * M_PI/2到达2 * M_PI的路上时翻转。 – Steve 2010-09-27 16:44:01

1

由此产生的变换是相同的:(CGAffineTransform){-1,0,0,-1,0,0}。 CoreAnimation选择最短的旋转方式,并且默认顺时针旋转(我认为)。

旋转的其他方式,最简单的方法是几乎-M_PI旋转(我不知道你究竟是如何接近得到它决定旋转的“错误”的方式之前)。

更复杂的方法是将其分解为两个旋转:一个从0到-M_PI/2,另一个从-M_PI/2到-M-PI。我想你可以设定动画的延迟要做到这一点...

+0

我摆弄这一段时间,但还没有找到一种方法来设置'CATransaction.'的延迟。我尝试在'CATransaction'中嵌套两个'UIView'动画块,第二个有一个延迟,但目前还没有运气。这可能是因为实际得到的东西是“CALayer”而不是“UIView”。也许?在这个问题中增加了这个版本。 – Steve 2010-09-27 04:00:03

+0

对于我正在尝试完成的事情,这是一个很好的建议(向一个方向旋转“显示更多”指示符,然后将其旋转回来。FYI,M_PI - 0.01以“几乎是值”的方式表现出色。“ – Keller 2012-08-08 15:54:34

3

我猜一个轴上的翻转是由苹果的图书馆内发生的万向节锁造成的。 99.999%的时间很容易解决,只是不使用精确的0,90,180,270和360度旋转。我在代码中看到过这样的事情,但我只是使用类似(M_PI * 0.99)而不是M_PI。如果你使用视频卡的矩阵乘法器和欧拉角,这总是一个问题。

要同时应用多个转换,可以将它们嵌套。这与OpenGL中的矩阵乘法完全相同。

// translate and scale at the same time 
float scale = 1.6; 
CATransform3D scaleMatrix = CATransform3DMakeScale(scale, scale, 1); 
CATransform3D finalMatrix = CATransform3DTranslate(scaleMatrix, frame.size.width/scale, frame.size.height/scale, 0); 
CABasicAnimation* animBottomTrans = [CABasicAnimation animationWithKeyPath:@"transform"]; 
[animBottomTrans setFromValue:[NSValue valueWithCATransform3D:finalMatrix]]; 
[animBottomTrans setToValue:[NSValue valueWithCATransform3D:CATransform3DIdentity]]; 
[animBottomTrans setDuration:duration]; 
[myLayer addAnimation:animBottomTrans forKey:@"transform"]; 

记住,因为这些嵌套你必须处理与之前在它之后来到任何变换变换。在这段代码中,我必须改变我翻译的数量,因为我已经缩放了。如果您在z轴上旋转90度,然后在y轴上旋转90度,则您只能在z轴和x轴上旋转(z轴旋转您的x和y轴)。