我是第一次使用一些核心动画,并且在实现可以翻转的扑克牌的过程中,我决定使用一个 CALayer 要显示内容(不确定我将如何获得两个方面,但这是另一个问题),我需要能够将其翻转,移动它等...

我在用着 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轴旋转,但这并不等于仅在两个单个轴周围通过PI将其翻转。这是嵌套的代码。


[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"];
有帮助吗?

解决方案

我相信,在这种情况下,您想要的是使用助手键盘,如所描述的 这个答案:

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"];

它应该使动画累积,并可能产生预期的效果。我自己没有尝试过这个,因此可能需要进行一些修补来获得您需要的确切结果。

当您直接使用转换时,核心动画将插入从当前值到指定变换的转换。它将找到到达该转换的最短途径,这将限制动画方向。如果您尝试将同一变换属性动画化两次,那么第二个值将简单地覆盖第一个,而不是将两个转换组合在一起。

但是,当使用这样的助手键盘时,核心动画将在您的起点和终点之间插值,因此您可以通过更改末端角度的符号来逆转方向。它优化了角度值的变化,而不是基础变换的变化。您还应该能够在键盘上结合动画,因为对于键盘操作的每种组合,都会为您生成转换。

其他提示

我猜想轴上的翻转是由苹果图书馆内发生的gimbal锁引起的。工作时间为99.999%的简单修复程序是不使用精确的0、90、180、270和360度旋转。我已经看到这样的事情在我的代码中发生,但是我只是使用(m_pi*0.99)而不是m_pi。如果您使用带有Euler角度的视频卡的矩阵乘数,这总是一个问题。

要同时应用多个变换,您可以嵌套它们。这完全像在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轴)。

最终的转换是相同的: (CGAffineTransform){-1,0,0,-1,0,0}. 。合流选择最短的旋转将解决问题,默认为顺时针旋转(我认为)。

旋转另一种方式的最简单方法是旋转 几乎 -M_PI (我不确定在决定旋转“错误”方式之前,您可以确切地获得多么近的距离)。

更复杂的方法是将其分为两个旋转:一个从0到-m_pi/2,一个从-m_pi/2到-m -pi。我认为您可以设置动画延迟以实现这一目标...

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top