8

私が達成しようとしているアニメーションを示すビデオを作成しました。これがここにあります。

ビデオは、側面から見たときのアクションを示していることに注意してください。カメラアイコンは、ユーザーのPOVを表します。これは基本的に、スケール変換によって達成されるZ軸間の平行移動のシミュレーションであり、X軸に沿って同時に独立した2ステップの3D回転が発生します。

見た目も音もシンプルですよね?間違い。これが機能しない理想的なコードです:

[UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
    view.transform = CGAffineTransformMakeScale(1.0, 1.0);
} completion:^(BOOL finished) {}];

[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
    CATransform3D rotation = CATransform3DIdentity;
    rotation.m34 = 1.0 / - 1800;
    rotation = CATransform3DRotate(rotation, - 20 * M_PI / 180.0f, 1, 0, 0);

    view.layer.transform = rotation;

} completion:^(BOOL finished) {
    [UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        view.layer.transform = CATransform3DIdentity;

    } completion:^(BOOL finished) {}];
}];

これを行うと、3D回転は完全に無視されます。私は他の多くのアプローチを試しましたが、それらはすべて失敗しました。

いくつかの要件:

  • スケールはできればCGAffineTransform
  • イージングは​​、特にローテーションで、図のようにする必要があります

もちろん、これらのいくつかを変更する必要がある解決策が出てきた場合、私は適応することができます。

助けてくれてありがとう。説明が必要な場合は、質問してください。

4

2 に答える 2

29

最初のアニメーションがキャンセルされない限り、同じプロパティをアニメーション化することはできません。コアアニメーションを使用し、2つのアニメーションまたは1つのキーフレームアニメーションを実行するようにドロップダウンする必要があります。

2つの変換アニメーション

スケーリング用に1つのアニメーションを作成し(必要に応じてz変換として実行できます)、回転用に1つのアニメーションを作成して、非常に具体的なキーパスを指定することで、互いにキャンセルされません。

CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scale.fromValue = @0.75; // Your from value (not obvious from the question)
scale.toValue = @1.0;
scale.duration = 0.4;
scale.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

CAKeyframeAnimation *rotate = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.x"];
rotate.values = @[@0.0, @(- 20 * M_PI / 180.0f), @0.0];
rotate.duration = 0.4;
rotate.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];

[view.layer addAnimation:scale forKey:@"move forward by scaling"];
[view.layer addAnimation:rotate forKey:@"rotate back and forth"];
view.transform = CGAffineTransformIdentity; // Set end value (animation won't apply the value to the model)

単一のキーフレームアニメーション

3つの非常に優れたキーフレームがあるため、3つのキーフレーム間でアニメーション化するコードは読みやすく理解しやすいでしょう。回転のタイミングとは別にスケーリングのタイミングを変更したい場合は、コントロールの一部が失われる可能性があります。

CATransform3D firstFrame  = CATransform3DMakeScale(0.75, 0.75, 1.0);
CATransform3D secondFrame = CATransform3DMakeScale(0.875, 0.875, 1.0); // halfway to 1.0 from 0.75
secondFrame = CATransform3DRotate(secondFrame, -20.0*M_PI/180.0, 1.0, 0.0, 0.0);
CATransform3D lastFrame   = CATransform3DIdentity;

CAKeyframeAnimation *scaleAndRotate = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
scaleAndRotate.values = @[[NSValue valueWithCATransform3D:firstFrame],
                          [NSValue valueWithCATransform3D:secondFrame],
                          [NSValue valueWithCATransform3D:lastFrame] ];
scaleAndRotate.duration = 1.0;
scaleAndRotate.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];

[view.layer addAnimation:scaleAndRotate forKey:@"entire animation"];
view.transform = CGAffineTransformIdentity; // Set end value (animation won't apply the value to the model)

視点

どちらの場合も、アニメーションビューのスーパーレイヤーにsublayerTransformを設定してパースペクティブを作成しました(変換を含むサブビューが1つだけであると想定しています)。

CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = 1.0 / - 1800.0;    
view.superview.layer.sublayerTransform = perspective;
于 2012-12-24T10:49:17.207 に答える
2

私は方法を見つけましたが、それはハックのようなものです。以下をせよ -

1)背景が透明なビューを作成します-(このビューは変換されます)2)1)のサブビューを作成します-(このビューは回転します)。

次に、ビュー1)のスケーリング変換とビュー2)のrottaion変換の2つの変換を作成し、それらを同時に適用します。

于 2013-12-21T07:49:29.693 に答える