12

ここでのBradLarsonの回答に示されているように、アニメーショングループアプローチに完全に適したアニメーション効果を得るには、入力に従ってアニメーションを進める必要があります。具体的には、タッチと検出されたタッチの位置。touchsMovedの処理は簡単です。タッチごとに要素の位置を設定できますが、CoreAnimationのアプローチのようにスムーズではありません。

溝のあるトラックに大理石があると想像してみてください。大理石を任意の位置に任意の速度で一方向または他の方向に押し込みたいです。アニメーションはそのようなことをしなければならず、タッチに応じてパスに沿って視覚要素を動かします。CAKeyframeAnimationにはパスビットが正確にありますが、フレームからフレームへの遷移は、他の要因ではなく、一方向の経過時間に基づいて行う必要があるようです。

1月31日更新-これまでの回答に感謝しますが、実際に問題を解決しているものはありません。オプションを選択するためにドラッグする円形のメニューがあります。すべてを一緒に移動する必要があり、回転変換が適用され、サブビューに逆回転変換が適用されたビューを使用して、アイコンがすべて適切な観覧車の向きで回転するように回避しました。アイコンがわずかに卵形のパスに沿ってアニメーション化されていると、本当に見栄えが良くなります...大理石の説明は、私がやろうとしていることを明確にするための試みです。おそらく、溝内を移動するすべての磁石をはじくように方向付けられた磁石を想像する方がよいでしょう。1つを移動すると、隣接する磁石も移動しますが、必ずしもドラッグされた磁石がパスのカーブに沿って移動する方向に移動する必要はありません。

今のところ問題は、1つの円で作成された単純なパスをたどることですが、速度や方向を計算せずに、タッチだけで位置を制御して、任意のパスに沿ってオブジェクトをアニメーション化する方法を知りたいです。

4

5 に答える 5

7

レイヤーツリーのタイムラインの階層的な性質を使用して、探しているものを実現できる場合があります。CAMediaTimingとの両方を含むをCAAnimation実装するオブジェクトCALayerは、親からタイムスペースを継承し、それを変更して(スケーリング、シフト、繰り返しを介して)子に伝播できます。speedレイヤーのプロパティを0.0に設定し、プロパティをtimeOffset手動で調整することにより、そのレイヤー(およびそのすべてのサブレイヤー)を通常の時間の概念から切り離すことができます。

あなたの場合、あなたがすることは、すべてのメニュー項目のアニメーションを定義して、CGPath時間t0からt1までの希望に沿った位置をアニメーション化し、各アニメーションに適切な間隔を置いて適切な間隔を保つことですアニメーションのaが0.0の場合、通常、アニメーションがレイヤーに追加された時点から開始すると解釈されるため、t 0を0.0にする場合は、0.0より大きい小さなイプシロンに設定する必要があります。timeOffsetbeginTime

CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animation.beginTime = 1e-100;
animation.duration = 1.0;
animation.fillMode = kCAFillModeBoth;
animation.removedOnCompletion = NO;
animation.path = path;
animation.calculationMode = kCAAnimationPaced;
animation.timeOffset = timeOffset;

speed次に、親レイヤー(これらのメニュー項目のみを含む)でプロパティを0.0に設定し、タッチイベントに応じてt0からt1timeOffsetの間の値に更新します。

このアプローチには、2つの潜在的な注意点があります。このレイヤーサブツリーで時間の性質を引き継いだため、他のプロパティを同時にアニメーション化することはおそらくできません。さらに、高速フリックのために惰性走行動作が必要な場合は、おそらく自分で時間を前向きにアニメートする必要があります。

于 2011-02-02T17:40:08.163 に答える
1

iOS 4.0以降をターゲットにしている場合は、新しいブロックベースのクラスメソッドを使用して、オブジェクトを表示するためのアニメーション化可能な変更を開始できます。したがって、タッチイベントから、ビューのプロパティにアニメーション化可能な変更を開始できます。

[UIView animateWithDuration:1.0 animations:^{
    yourView.alpha = 0.0; // fade out yourView over 1 second
}];

注意:これは、場所など、ビュー上の別のプロパティへの変更と同じくらい簡単です。この方法で、ビューの次のプロパティをアニメーション化できます。

@property frame
@property bounds
@property center
@property transform
@property alpha
@property backgroundColor
@property contentStretch

以前のバージョンのiOSをターゲットにしている場合は、UIViewbeginAnimationsメソッドとcommitAnimationsメソッドを使用してアニメーションブロックを作成する必要あります

[UIView beginAnimations:nil context:context];
[UIView setAnimationDuration:1.0]; 
yourView.alpha = 0.0;
[UIView commitAnimations];

このようなものは本当にうまく機能し、使い始めたら、中毒にならないように注意する必要があります。;)

コメントの更新:

大理石の位置をタッチイベントの位置にバインドできます。touchesEndedイベントを取得したら、アニメーションブロックを使用して大理石の位置をアニメーション化できます。

于 2011-01-18T03:25:58.030 に答える
1

速度=距離/時間。動かしたタッチや時間に応じて遅延を与えることで試すことができます。touchesBeganメソッドとtouchesEndedメソッドの間の時間を計算できます。

于 2011-01-23T09:52:34.060 に答える
0

私はあなたが何をしたいのかを正確に理解しているとは完全にはわかりませんが...ユーザーの指がどこにあっても大理石を描くだけではどうですか?アニメーションは必要ありません。ユーザーが手放した後も大理石を動かし続けたい場合は、勢いの概念を維持し、それを使用して大理石の速度低下をアニメートする必要があります。そのためにCoreAnimationまたはタイマーのいずれかを使用できます。

于 2011-01-26T22:52:17.577 に答える
0

タッチを動かして速度を計算し、それをローカル変数に追加して、ブロックがタイマーを介して変更できるようにします。

つまり、移動したタッチでは、前の速度の方向を念頭に置いて速度計算を行います。タッチが終了したら、ブロックを発射して「大理石」を変換し、必要に応じて速度を減衰させます。ユーザーが大理石を再度移動した場合は、ローカル変数を変更します。これにより、タッチの方向に応じて、大理石のアニメーションが高速化されるか、低速化/方向が変更されます。

于 2011-01-27T10:06:36.753 に答える