ios - 終了 - uiview animation 停止




レイヤーのアニメーションの一時停止と再開を理解する (2)

私はCore Animation Programming Guideのアニメーションを勉強していますが、レイヤーのアニメーションを一時停止して再開するのに悩まされます。

このドキュメントでは、明確な説明なしにアニメーションを一時停止して再開する方法を教えています。 私は、鍵は、 timeOffsetbeginTimeメソッドがCAlayerかを理解することだと思います。

これらのコードは、アニメーションを一時停止してから再開します。 resumeLayerメソッドでは、 layer.beginTime = timeSincePause; この行は本当に私を混乱させます。

-(void)pauseLayer:(CALayer*)layer {
   CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
   layer.speed = 0.0;
   layer.timeOffset = pausedTime;
}

-(void)resumeLayer:(CALayer*)layer {
   CFTimeInterval pausedTime = [layer timeOffset];
   layer.speed = 1.0;
   layer.timeOffset = 0.0;
   layer.beginTime = 0.0;
   CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
   layer.beginTime = timeSincePause;
}

どんな助けもありがとう。


CAMediaTimingのヘッダファイルには、次のコードがあります。

/* The begin time of the object, in relation to its parent object, if
 * applicable. Defaults to 0. */

@property CFTimeInterval beginTime;

/* The basic duration of the object. Defaults to 0. */

@property CFTimeInterval duration;

/* The rate of the layer. Used to scale parent time to local time, e.g.
 * if rate is 2, local time progresses twice as fast as parent time.
 * Defaults to 1. */

@property float speed;

/* Additional offset in active local time. i.e. to convert from parent
 * time tp to active local time t: t = (tp - begin) * speed + offset.
 * One use of this is to "pause" a layer by setting `speed' to zero and
 * `offset' to a suitable value. Defaults to 0. */

@property CFTimeInterval timeOffset;

何が重要な数式です:

t =(tp-begin)*速度+オフセット

この式は、グローバル時間(または親時間、tp)がレイヤのローカル時間にどのようにマッピングされるかを定義します。 そして、この公式は、リストされたコードのすべてを説明することができます:

  1. 時刻Aでは、アニメーションが一時停止されます。 speed = 0、timeOffset = pauseTimeの設定後、レイヤーのローカルタイムはpauseTimeと等しくなります。 speed = 0のため、現地時間はそれ以上増加しません。
  2. 時刻Bでは、アニメーションが再開されます。 speed = 1.0、timeOffset = 0、beginTime = 0を設定すると、レイヤのローカルタイムは(timePause + timeSinacePause)のグローバルタイム(またはtp)になります。 しかし、アニメーションは#Aの時点から開始する必要があるので、beginTime = timeSincePausedを設定してから、レイヤのローカル時間はtimePauseに等しくなります。 原因のため、一時停止したポイントからアニメーションが続行されます。


docsから:

beginTime

beginTime親オブジェクトに対する受信者の開始時刻を指定します(該当する場合)。 (必須)

それはhereから取ったそれの素晴らしい説明がありhere

アニメーションがアニメーショングループ内にある場合、beginTimeはその親オブジェクトの先頭であるアニメーショングループからのオフセットです。 したがって、アニメーションのbeginTimeが5の場合、アニメーショングループの開始から5秒後に開始されます。

アニメーションがレイヤーに直接追加された場合でも、beginTimeは親オブジェクトの先頭からのオフセットです(レイヤー)。 しかし、レイヤーの始まりは過去1であるため、アニメーションを5秒間遅らせるためにbeginTimeを5に設定することはできません。レイヤーの開始から5秒後はおそらく過去の時間であるためです。 私が通常気に入っているのは、アニメーションがレイヤーに追加されたときの相対的な遅延です(addTimeで示されます)。

これは、ログに追加された質問のコードです。

- (IBAction)start:(UIButton *)sender
{    
    [UIView animateWithDuration:10 animations:^() {//Move square to x=300
    }completion:^(BOOL finished){}];
}

- (IBAction)pause:(UIButton *)sender
{
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
    layer.speed = 0.0;
    layer.timeOffset = pausedTime;
    NSLog(@"pausedTime: %f",pausedTime);
}

- (IBAction)resume:(UIButton *)sender
{
    CFTimeInterval pausedTime = [layer timeOffset];
    layer.speed = 1.0;
    layer.timeOffset = 0.0;
    layer.beginTime = 0.0;
    NSLog(@"CACurrentMediaTime: %f",[layer convertTime:CACurrentMediaTime() fromLayer:nil]);
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    NSLog(@"timeSincePause: %f",timeSincePause);
    layer.beginTime = timeSincePause;
}

出力:

pausedTime: 20000
CACurrentMediaTime: 20005
timeSincePause: 5 // <- that's your begin time. When you hit resume you want to begin the animation from that relative time.

すべてをまとめてみると、

アニメーションのデュレーションは合計10で、5でアニメーションを停止しました。また、アニメーションを再開すると、そのアニメーションをbeginTimeにします。

だから、私は一時停止時間を保存し、現在の時間から引いて、相対アニメーション時間を取得します。





calayer