5

私は初めていくつかのCoreAnimationを使用していて、裏返すことができるトランプを実装する過程でCALayer、コンテンツを表示するためにaを使用することにしました(どのように両面を取得するのかわかりません) 、しかしそれは別の質問です)そして私はそれをひっくり返したり、動かしたりすることができる必要があります...

私は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]; 

2番目の質問は次のようになります:一度に2つの変換を実行するにはどうすればよいですか?2つをネストしようとしましCATransactionsたが、2つ目は最初の1つをオーバーライドします。また、x軸とy軸を中心に回転するように、回転のベクトルを2Dに変更しようとしましたが、これは、2つの個別の軸を中心に円周率で反転することと同じではありません。ネストされたコードは次のとおりです。


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

そして、これが私が今いるところです。それはすべて、1つの例外を除いて機能します。カードが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"];
4

3 に答える 3

11

この場合に必要なのは、この回答で説明されているようなヘルパーキーパスを使用することだと思います。

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

アニメーションを累積的にして、目的の効果を生み出すことができます。私はこれを自分で試したことがないので、必要な正確な結果を得るには、いじくり回す必要があるかもしれません。

トランスフォームを直接操作している場合、CoreAnimationはトランスフォームを現在の値から指定されたトランスフォームに補間します。その変換に到達するための最短パスが検出され、アニメーションの方向が制限されます。同じ変換プロパティを2回アニメーション化しようとすると、2番目の値は最初の値をオーバーライドするだけで、2つの変換を結合することはありません。

ただし、このようなヘルパーキーパスを使用する場合、Core Animationは開始角度と終了角度の間を補間するため、終了角度の符号を変更することで方向を逆にすることができます。基になる変換の変更ではなく、角度値の変更を最適化します。また、キーパス操作の組み合わせごとに内部で変換が生成されるため、キーパスでアニメーションを組み合わせることができるはずです。

于 2010-09-27T15:42:21.633 に答える
3

軸の反転は、Appleのライブラリ内で発生しているジンバルロックが原因であると推測しています。99.999%の確率で機能する簡単な修正は、正確な0、90、180、270、および360度の回転を使用しないことです。このようなことが私のコードで発生するのを見てきましたが、M_PIの代わりに(M_PI * 0.99)のようなものを使用しています。オイラー角を持つビデオカードの行列乗数を使用している場合、これは常に問題になります。

複数の変換を同時に適用するには、それらをネストできます。これは、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軸を入れ替えます)。

于 2010-11-22T18:38:42.070 に答える
2

結果の変換は同じです:(CGAffineTransform){-1,0,0,-1,0,0}。CoreAnimationは、トリックを実行する最短の回転を選択し、デフォルトで時計回りに回転します(私は思います)。

他の方向に回転させる最も簡単な方法は、ほぼ -M_PI回転させることです(「間違った」方向に回転することを決定する前に、どれだけ近づくことができるか正確にはわかりません)。

より複雑な方法は、2つのローテーションに分割することです。1つは0から-M_PI / 2まで、もう1つは-M_PI/2から-M-PIまでです。これを実現するためにアニメーションの遅延を設定できると思います...

于 2010-09-27T00:59:32.207 に答える