[英]Trying to delay CABasicAnimation position and opacity of layer by 3 seconds but
我正在嘗試使用 setBeginTime 將圖層不透明度和位置的動畫延遲 3 秒。 我將圖層稱為 boxLayer。 動畫運行良好,但是在前 3 秒(圖層不應該顯示),圖層以其最終位置和不透明度顯示。 不應該。 組動畫不能解決問題。 有人可以幫忙嗎? 見下面的代碼:
// Create an animation that will change the opacity of a layer
CABasicAnimation *fader = [CABasicAnimation animationWithKeyPath:@"opacity"];
// It will last 1 second and will be delayed by 3 seconds
[fader setDuration:1.0];
[fader setBeginTime:CACurrentMediaTime()+3.0];
// The layer's opacity will start at 0.0 (completely transparent)
[fader setFromValue:[NSNumber numberWithFloat:startOpacity]];
// And the layer will end at 1.0 (completely opaque)
[fader setToValue:[NSNumber numberWithFloat:endOpacity]];
// Add it to the layer
[boxLayer addAnimation:fader forKey:@"BigFade"];
// Maintain opacity to 1.0 JUST TO MAKE SURE IT DOES NOT GO BACK TO ORIGINAL OPACITY
[boxLayer setOpacity:endOpacity];
// Create an animation that will change the position of a layer
CABasicAnimation *mover = [CABasicAnimation animationWithKeyPath:@"position"];
// It will last 1 second and will be delayed by 3 seconds
[mover setDuration:1.0];
[mover setBeginTime:CACurrentMediaTime()+3.0];
// Setting starting position
[mover setFromValue:[NSValue valueWithCGPoint:CGPointMake(startX, startY)]];
// Setting ending position
[mover setToValue:[NSValue valueWithCGPoint:CGPointMake(endX, endY)]];
// Add it to the layer
[boxLayer addAnimation:mover forKey:@"BigMove"];
// Maintain the end position at 400.0 450.0 OTHERWISE IT IS GOING BACK TO ORIGINAL POSITION
[boxLayer setPosition:CGPointMake(endX, endY)];
問題是您將boxLayer
的position
和opacity
屬性設置為它們的最終值。 你需要:
將boxLayer
屬性設置為它們的起始值,而不是它們的結束值(這就是為什么它從結束位置/不透明度開始......通常如果動畫立即開始,這不是問題,但因為你推遲了開始,使用結束位置是有問題的);
對於您的兩個動畫,您必須將removedOnCompletion
更改為NO
並將fillMode
更改為kCAFillModeForwards
(這是防止它在完成后恢復到原始位置的正確方法)。
因此:
// Create an animation that will change the opacity of a layer
CABasicAnimation *fader = [CABasicAnimation animationWithKeyPath:@"opacity"];
// It will last 1 second and will be delayed by 3 seconds
[fader setDuration:1.0];
[fader setBeginTime:CACurrentMediaTime()+3.0];
// The layer's opacity will start at 0.0 (completely transparent)
[fader setFromValue:[NSNumber numberWithFloat:startOpacity]];
// And the layer will end at 1.0 (completely opaque)
[fader setToValue:[NSNumber numberWithFloat:endOpacity]];
// MAKE SURE IT DOESN'T CHANGE OPACITY BACK TO STARTING VALUE
[fader setRemovedOnCompletion:NO];
[fader setFillMode:kCAFillModeForwards];
// Add it to the layer
[boxLayer addAnimation:fader forKey:@"BigFade"];
// SET THE OPACITY TO THE STARTING VALUE
[boxLayer setOpacity:startOpacity];
// Create an animation that will change the position of a layer
CABasicAnimation *mover = [CABasicAnimation animationWithKeyPath:@"position"];
// It will last 1 second and will be delayed by 3 seconds
[mover setDuration:1.0];
[mover setBeginTime:CACurrentMediaTime()+3.0];
// Setting starting position
[mover setFromValue:[NSValue valueWithCGPoint:CGPointMake(startX, startY)]];
// Setting ending position
[mover setToValue:[NSValue valueWithCGPoint:CGPointMake(endX, endY)]];
// MAKE SURE IT DOESN'T MOVE BACK TO STARTING POSITION
[mover setRemovedOnCompletion:NO];
[mover setFillMode:kCAFillModeForwards];
// Add it to the layer
[boxLayer addAnimation:mover forKey:@"BigMove"];
// SET THE POSITION TO THE STARTING POSITION
[boxLayer setPosition:CGPointMake(startX, startY)];
就我個人而言,我認為您正在為使用視圖上的基於塊的動畫更容易完成的事情做很多工作(出於本演示的目的,我假設您的boxLayer
是一個名為box
的控件的CALayer
) . 如果您這樣做,您也不需要 Quartz 2D:
box.alpha = startOpacity;
box.frame = CGRectMake(startX, startY, box.frame.size.width, box.frame.size.height);
[UIView animateWithDuration:1.0
delay:3.0
options:0
animations:^{
box.alpha = endOpacity;
box.frame = CGRectMake(endX, endY, box.frame.size.width, box.frame.size.height);
}
completion:nil];
這篇文章很好地解釋了為什么你不應該使用 removeOnCompletion 和 fillMode https://www.objc.io/issues/12-animations/animations-explained/
就我而言,我正在為視圖層設置動畫,該視圖層用作導航但延遲了該視圖內的反彈動畫; 我需要在圖層上更新這兩個位置,因為它可以被關閉然后再次顯示。 一旦動畫完成,使用removedOnCompletion 不會更新圖層的值
我這樣做的方法是更新 CATransaction 完成塊中的層
CATransaction.setCompletionBlock {
// update the layer value
}
CATransaction.begin()
// setup and add your animation
CATransaction.commit()
要使用beginTime
您應該對動畫對象進行必要的配置,並將fillMode
設置為kCAFillModeBackwards
例如
zoomAnimation.fillMode = kCAFillModeBackwards;
這是在 Apple 文檔中說的:
使用 beginTime 屬性設置動畫的開始時間。 通常,動畫在下一個更新周期開始。 您可以使用 beginTime 參數將動畫開始時間延遲幾秒鍾。 將兩個動畫鏈接在一起的方法是設置一個動畫的開始時間以匹配另一個動畫的結束時間。 如果您延遲動畫的開始,您可能還需要將 fillMode 屬性設置為 kCAFillModeBackwards。 這種填充模式會使圖層顯示動畫的起始值,即使圖層樹中的圖層對象包含不同的值。 如果沒有這種填充模式,您會在動畫開始執行之前看到跳轉到最終值。 其他填充模式也可用。
另外,來自羅布的回答:
對於您的兩個動畫,您必須將 removedOnCompletion 更改為 NO 並將 fillMode 更改為 kCAFillModeForwards(這是防止它在完成后恢復到原始位置的正確方法)。
這是一種有爭議的聲明,因為:
移除動畫后,表示層將回退到模型層的值,並且由於我們從未修改過該層的位置,因此我們的飛船會重新出現在它開始的位置。 有兩種方法可以處理這個問題:
第一種方法是直接在模型層更新屬性。 這是推薦的方法,因為它使動畫完全可選。
或者,您可以通過將其 fillMode 屬性設置為 kCAFillModeForwards 來告訴動畫保持其最終狀態,並通過將 removedOnCompletion 設置為 NO 來防止它被自動刪除。 但是,保持模型層和表示層同步是一個很好的做法,因此應謹慎使用此方法。
來自https://www.objc.io/issues/12-animations/animations-explained/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.