4

私はこのような折りたたみメニューアニメーションを作成しようとしています:http://vimeo.com/41495357

この時点で、画面上で指をドラッグするとアニメーションは機能しますが、メニューを開いた状態から閉じた状態、または閉じた状態から直接開いた状態にアニメーション化しようとすると、スライドして離れたメインビューがビューの右側に整列しません。それが展開しています。アニメーションが終了すると整列されますが、途中では整列されません。また、展開中のビューのエッジは、アニメーション中にビューの境界の外側に消えるように見えます。

レイヤーの実際の展開はlayoutSublayersで行われるため、レイヤーの幅が変更されると、そのサブレイヤーでの変換が計算されます。このプロジェクトで変換を計算するための数学を見つけました:https ://github.com/MassiveHealth/O​​paque

// Configure the layer bounds and midpoints
CGRect halfRect = CGRectMake(0, 0, self.fullWidth / 2, self.bounds.size.height);
self.rightImageLayer.bounds = halfRect;
self.leftImageLayer.bounds = halfRect;
CGPoint midPoint = CGPointMake(0.5 * self.bounds.size.width, 0.5 * self.bounds.size.height);
self.rightImageLayer.position = midPoint;
self.leftImageLayer.position = midPoint;

// Calculate transforms
CGFloat l = 0.5 * self.fullWidth;
CGFloat y = 0.5 * self.bounds.size.width;
CGFloat theta = acosf(y/l);
CGFloat z = l * sinf(theta);
CGFloat topAngle = theta * -1;
CGFloat bottomAngle = theta;

CATransform3D transform = CATransform3DMakeTranslation(0.0, 0.0, -z);
self.rightImageLayer.transform = CATransform3DRotate(transform, topAngle, 0.0, 1.0, 0.0);
self.leftImageLayer.transform = CATransform3DRotate(transform, bottomAngle, 0.0, 1.0, 0.0);

これは、展開アニメーションの開始を担当するコードです。(現在、メニューは画面の幅全体に展開されます)

self.foldingLayer.frame = self.view.bounds;
self.slidingLayer.frame = CGRectMake(self.view.frame.size.width, 0, self.slidingLayer.frame.size.width, self.slidingLayer.frame.size.height);

なぜこれらのアニメーションが整列しないのですか?おそらく数学は間違っていますか?https://github.com/honcheng/PaperFold-for-iOShttps://github.com/xyfeng/XYOrigamiなどのプロジェクトのサンプルコードを見ましたが、わかりません。

アップデート

Tillの回答に基づいて、スライディングレイヤー用にこのキーフレームアニメーションを作成しました。アニメーションがまだ整列していないので、キーフレームの計算が間違っている必要がありますか?

CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position.x"];

NSUInteger steps = 100;
CGFloat totalFoldViewWidth = self.view.bounds.size.width;
NSMutableArray *values = [NSMutableArray arrayWithCapacity:steps];

for(NSUInteger i = 0; i < steps; i++) {
    CGFloat fraction = (CGFloat)i / steps;
    CGFloat foldViewWidth = fraction * totalFoldViewWidth;
    CGFloat l = 0.5 * totalFoldViewWidth;
    CGFloat y = 0.5 * foldViewWidth;
    CGFloat angle = acosf(y/l);
    CGFloat projectionWidth = cosf(angle) * totalFoldViewWidth;
    [values addObject:[NSNumber numberWithFloat:projectionWidth]];
}
animation.calculationMode = kCAAnimationLinear;
[animation setValues:values];
[animation setDuration:3.0];

[self.slidingLayer addAnimation:animation forKey:@"slideAnimation"];
4

2 に答える 2

3

あなたは間違った方向から問題に取り組んでいると思います。距離から角度を計算したいのですが、その逆はありません。折りたたみアニメーションの各辺の角度を計算する場合は、基本的なピタゴラス演算を使用します。明らかに、開口距離のサイズと斜辺のサイズ(完全に開いたときのビューのサイズの半分)がわかります。

コード内:

CGFloat otherSide = 0.5 * openingWidth; // halve because we have two sides
CGFloat hypotenuse = 0.5 * unfoldedViewTotalWidth; // halve because we have to sides
CGFloat angle = asinf(otherSide / hypotenuse);
CGFloat rightAngle = -1 * (M_PI_2 - angle);
CGFloat leftAngle = M_PI_2 - angle;

これらの角度を使用して、折り畳みビューの左側と右側の回転を設定できます。

左側のアンカーポイントを(0.0、0,5)に設定し、右側のアンカーポイントを(1.0、0.5)に設定し、右側の平行移動もアニメートするように注意してください。

お役に立てれば!乾杯!

于 2012-10-05T16:01:53.653 に答える
0

それは確かにあなたの数学の問題です。そのビューの距離は、折りたたまれたビューの投影幅によって異なります。その幅は、角度によっては厳密には直線的ではありません。

projectionWidth = cos(angle) * foldViewWidth

言い換えると、40度は20度とはまったく異なるものになり、その関係は線形ではなく、その角度の正弦に基づいています。

したがって、線形アニメーションは機能しません。平行移動と回転を一致させるには、折りたたまれたビューの投影幅に基づいてフレームアニメーションを作成する必要があります。

于 2012-10-03T11:19:11.740 に答える