CALayerのアニメーションのコールバックがどこにあるのか(または何かあるのか)疑問に思っています。具体的には、フレーム、位置などの変更のような暗黙のアニメーションの場合、UIViewでは、次のようなことができます。
[UIView beginAnimations:@"SlideOut" context:nil];
[UIView setAnimationDuration:.3];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animateOut:finished:context:)];
CGRect frame = self.frame;
frame.Origin.y = 480;
self.frame = frame;
[UIView commitAnimations];
具体的には、setAnimationDidStopSelector
はCALayerのアニメーションに必要なものです。そのようなものはありますか?
TIA。
私は自分の質問に答えました。次のようにCABasicAnimation
を使用してアニメーションを追加する必要があります。
CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"frame"];
anim.fromValue = [NSValue valueWithCGRect:layer.frame];
anim.toValue = [NSValue valueWithCGRect:frame];
anim.delegate = self;
[layer addAnimation:anim forKey:@"frame"];
そしてデリゲートメソッドを実装しますanimationDidStop:finished:
そして、あなたは行ってもいいはずです。この機能が存在することに感謝します! :D
完了ブロックハンドラーを備えたCATransactionを使用できます。
[CATransaction begin];
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
[pathAnimation setDuration:1];
[pathAnimation setFromValue:[NSNumber numberWithFloat:0.0f]];
[pathAnimation setToValue:[NSNumber numberWithFloat:1.0f]];
[CATransaction setCompletionBlock:^{_lastPoint = _currentPoint; _currentPoint = CGPointMake(_lastPoint.x + _wormStepHorizontalValue, _wormStepVerticalValue);}];
[_pathLayer addAnimation:pathAnimation forKey:@"strokeEnd"];
[CATransaction commit];
フェードインフェードアウトを行うために、このゴミで4時間を無駄にした。コード内のコメントに注意してください。
[CATransaction begin];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.duration = 0.3;
animation.fromValue = [NSNumber numberWithFloat:0.0f];
animation.toValue = [NSNumber numberWithFloat:1.0f];
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeBoth;
/// [box addAnimation:animation forKey:@"j"]; Animation will not work if added here. Need to add this only after the completion block.
[CATransaction setCompletionBlock:^{
CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation2.duration = 0.3;
animation2.beginTime = CACurrentMediaTime()+1;
animation2.fromValue = [NSNumber numberWithFloat:1.0f];
animation2.toValue = [NSNumber numberWithFloat:0.0f];
animation2.removedOnCompletion = NO;
animation2.fillMode = kCAFillModeBoth;
[box addAnimation:animation2 forKey:@"k"];
}];
[box addAnimation:animation forKey:@"j"];
[CATransaction commit];
Swift 3.0 bennytheminkのソリューションに基づいた3.0の答えは次のとおりです。
// Begin the transaction
CATransaction.begin()
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.duration = duration //duration is the number of seconds
animation.fromValue = 0
animation.toValue = 1
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
circleLayer.strokeEnd = 1.0
// Callback function
CATransaction.setCompletionBlock {
print("end animation")
}
// Do the actual animation and commit the transaction
circleLayer.add(animation, forKey: "animateCircle")
CATransaction.commit()
簡単にできませんでした。
[weak self]
を忘れないでください。そうしないとクラッシュします。
func animeExample() {
CATransaction.begin()
let a = CABasicAnimation(keyPath: "fillColor")
a.fromValue, duration = ... etc etc
CATransaction.setCompletionBlock{ [weak self] in
self?.animeExample()
self?.ringBell()
print("again...")
}
someLayer.add(a, forKey: nil)
CATransaction.commit()
}
。 。 。 。 。注-重要なヒント>>>>>
重要なヒントのためにこの投稿を中断します。
あなた[〜#〜] [〜#〜]にはsetCompletionBlock[〜#〜] before [〜#〜]行someLayer.add。
Googleで詳細を読むこともできますが、一般的にはこの順序で行うことが重要です。そして今、投稿に戻ります!
<<<<<注-重要なヒント。 。 。 。 。
この例では、再び自分自身を呼び出します。
もちろん、任意の関数を呼び出すことができます。
iOSアニメーションを初めて使用する場合の注意:
「_」は(forKey
のように)無関係で、めったに使用されないです。 nilに設定します。設定する場合は、「任意の文字列」に設定します。
「keyPath」は、実際には実際の「アニメーション化するもの」です。文字通りレイヤーのプロパティ "opacity"、 "backgroundColor"などのようなものですが、string 。 (単に「欲しいもの」を入力することはできません。レイヤーの実際のプロパティの名前である必要があり、アニメート可能でなければなりません。)
繰り返します:「キー」(めったに使用しない-単にnilに設定する)と「キーパス」はまったく関係ありません。
多くの場合、これら2つがconfused(愚かな名前のおかげ)であるコード例がありますが、これはあらゆる種類の問題を引き起こします。
別の方法として、デリゲートを使用することもできますが、(A)自己完結型でどこでも使用できるため、(B)通常複数のアニメがあるため、完了ブロックを使用する方がはるかに簡単です。デリゲートは退屈です。
Googleでこのページを見つけた人への注意:アニメーションオブジェクトの「デリゲート」プロパティを通知を受け取るオブジェクトに設定し、そのオブジェクトの.mで「animationDidStop」メソッドを実装することで、本当に仕事を完了できます。ファイル。試してみたところ、うまくいきました。ジョー・ブローがそれが正しい方法ではないと言った理由はわかりません。
Swift 4 +では、delegate
を追加しました
class CircleView: UIView,CAAnimationDelegate {
...
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.delegate = self//Set delegate
アニメーション完了コールバック-
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
print("Animation END")
}
Swift 5.
func blinkShadow(completion: @escaping (() -> Void)) {
CATransaction.begin()
let animation = CABasicAnimation(keyPath: "shadowRadius")
animation.fromValue = layer.shadowRadius
animation.toValue = 0.0
animation.duration = 0.1
animation.autoreverses = true
CATransaction.setCompletionBlock(completion)
layer.add(animation, forKey: nil)
CATransaction.commit()
}
CATransaction
をいじりたくない場合。アニメーションオブジェクトにコールバックをカプセル化する拡張機能を作成しました。
コードは次のスニペットにあります: https://gitlab.com/snippets/1786298
そして、次のように使用できます:
let appearAnimation = CASpringAnimation(keyPath: "transform")
appearAnimation.fromValue = contentView.layer.transform
appearAnimation.toValue = CATransform3DIdentity
appearAnimation.mass = 0.65
appearAnimation.duration = appearAnimation.settlingDuration
appearAnimation.isAdditive = true
appearAnimation.onCompletion {
completed()
}
CAAnimationオブジェクトを設定するときに、特定のアニメーションの名前を設定できます。 animationDiStop:finishedでは、提供されたtheAnimationオブジェクトの名前を比較するだけで、アニメーションに基づいて特定の機能を実行できます。