我需要鏈接動畫,CABasicAnimation或CAAnimationGroup,但我不知道該怎麼做,我所做的唯一的事情就是所有動畫同時執行相同的操作層。如何在iOS應用程序中鏈接不同的CAAnimation
我該怎麼辦?
例如,具有其內容的層設置爲一個汽車圖像:
第一:移動X點至右
第二:旋轉90ª向左
第三:移動X點
第4步:縮放圖層
所有這些動畫必須以非常精確的方式執行,但我做不到:S
BTW:我不是英語,對不起,如果我改變了我的語法一些錯誤:d
我需要鏈接動畫,CABasicAnimation或CAAnimationGroup,但我不知道該怎麼做,我所做的唯一的事情就是所有動畫同時執行相同的操作層。如何在iOS應用程序中鏈接不同的CAAnimation
我該怎麼辦?
例如,具有其內容的層設置爲一個汽車圖像:
第一:移動X點至右
第二:旋轉90ª向左
第三:移動X點
第4步:縮放圖層
所有這些動畫必須以非常精確的方式執行,但我做不到:S
BTW:我不是英語,對不起,如果我改變了我的語法一些錯誤:d
TL;博士:您需要以前完成後手動添加每個動畫。
沒有內置的方式來添加順序動畫。你可能設置每個動畫的延遲是所有以前的動畫的總和,但我不會推薦它。
相反,我會創建所有的動畫,並將它們按照它們應該運行的順序添加到可變數組中(使用數組作爲隊列)。然後,通過將自己設置爲所有動畫的動畫代理,只要動畫完成,就可以獲取animationDidStop:finished:
回調。
在該方法中,您將從數組中刪除第一個動畫(意味着下一個動畫)並將其添加到圖層中。由於您是委託人,因此您將獲得第二個動畫,在這種情況下,animationDidStop:finished:
回調將再次運行,並將下一個動畫從可變陣列中移除並添加到圖層。
一旦動畫數組爲空,所有動畫都會運行。
一些示例代碼,讓你開始。首先,你設置你所有的動畫:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
[animation setToValue:(id)[[UIColor redColor] CGColor]];
[animation setDuration:1.5];
[animation setDelegate:self];
[animation setValue:[view layer] forKey:@"layerToApplyAnimationTo"];
// Configure other animations the same way ...
[self setSequenceOfAnimations:[NSMutableArray arrayWithArray: @[ animation, animation1, animation2, animation3, animation4, animation5 ] ]];
// Start the chain of animations by adding the "next" (the first) animation
[self applyNextAnimation];
然後在委託回調您簡單地套用一個動畫再次
- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished {
[self applyNextAnimation];
}
- (void)applyNextAnimation {
// Finish when there are no more animations to run
if ([[self sequenceOfAnimations] count] == 0) return;
// Get the next animation and remove it from the "queue"
CAPropertyAnimation * nextAnimation = [[self sequenceOfAnimations] objectAtIndex:0];
[[self sequenceOfAnimations] removeObjectAtIndex:0];
// Get the layer and apply the animation
CALayer *layerToAnimate = [nextAnimation valueForKey:@"layerToApplyAnimationTo"];
[layerToAnimate addAnimation:nextAnimation forKey:nil];
}
我使用的是自定義鍵layerToApplyAnimationTo
使每個動畫知道它的層(它僅適用於setValue:forKey:
和valueForKey:
)。
大衛,你怎麼不喜歡爲每個動畫設置不同的beginTime值?編寫代碼通常比使用完成方法鏈接動畫更簡單,而且它完全符合我的經驗。 – 2012-07-31 20:31:43
@DuncanC它感覺脆弱的我。添加,刪除或更改動畫的順序變得更麻煩並且容易出錯。 – 2012-08-01 05:25:22
非常感謝你,我認爲這兩個答案對我來說都是有效的,但大衛對我的看法更好。 – torhector2 2012-08-01 09:30:53
什麼大衛建議工作正常,但我會建議一種不同的方式。
如果所有動畫都在同一圖層上,則可以創建一個動畫組,並使每個動畫具有不同的beginTime
,其中第一個動畫開始於beginTime
0,並且每個新動畫在動畫之前。
但是,如果您的動畫在不同的圖層上,則不能使用動畫組(動畫組中的所有動畫必須在同一圖層上執行操作)。在這種情況下,您需要提交單獨的動畫,其中有一個beginTime
是從CACurrentMediaTime()
補償,例如:
CGFloat totalDuration = 0;
CABasicAnimation *animationOne = [CABasicAnimation animationWithKeyPath: @"alpha"];
animationOne.beginTime = CACurrentMediaTime(); //Start instantly.
animationOne.duration = animationOneDuration;
...
//add animation to layer
totalDuration += animationOneDuration;
CABasicAnimation *animationTwo = [CABasicAnimation animationWithKeyPath: @"position"];
animationTwo.beginTime = CACurrentMediaTime() + totalDuration; //Start after animation one.
animationTwo.duration = animationTwoDuration;
...
//add animation to layer
totalDuration += animationTwoDuration;
CABasicAnimation *animationThree = [CABasicAnimation animationWithKeyPath: @"position"];
animationThree.beginTime = CACurrentMediaTime() + totalDuration; //Start after animation three.
animationThree.duration = animationThreeDuration;
...
//add animation to layer
totalDuration += animationThreeDuration;
如果這有助於其他人:如果你使用動畫組(即不是這裏的代碼片段,但大衛的第一段),那麼animation.beginTim是相對於組... ....所以你不把它設置爲CACurrentMediaTime(),你只需將它設置爲totalDuration。這讓我感到困惑了幾分鐘.... – xaphod 2015-06-06 09:38:00
無論是大衛的做法或BEGINTIME財產都ok將動畫鏈接。見http://wangling.me/2011/06/time-warp-in-animation.html - 它闡明瞭使用beginTime和其他CAMediaTiming協議屬性。
使用KVC。每個動畫的關鍵字setValue。之後,在animationDidStop中,您可以定義哪些動畫已停止並在鏈中運行。
- (void)moveXrightAnimation {
CABasicAnimation* theAnimation = ...
[theAnimation setValue:@"movexright" forKey:@"animationID"];
//animation
}
- (void)rotate90leftAnimation {
CABasicAnimation* theAnimation = ...
[theAnimation setValue:@"rotate90left" forKey:@"animationID"];
//animation
}
- (void)moveXpointAnimation {
CABasicAnimation* theAnimation = ...
[theAnimation setValue:@"movexpoint" forKey:@"animationID"];
//animation
}
- (void)scaleAnimation {
CABasicAnimation* theAnimation = ...
[theAnimation setValue:@"scale" forKey:@"animationID"];
//animation
}
#pragma mark - CAAnimationDelegate
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
if([[anim valueForKey:@"animationID"] isEqual:@"movexright"]) {
[self rotate90leftAnimation];
}
if([[anim valueForKey:@"animationID"] isEqual:@"rotate90left"]) {
[self moveXpointAnimation];
}
if([[anim valueForKey:@"animationID"] isEqual:@"movexpoint"]) {
[self scaleAnimation];
}
}
下面是斯威夫特的解決方案:
var animations = [CABasicAnimation]()
var animation1 = CABasicAnimation(keyPath: "key_path_1")
// animation set up here, I've included a few properties as an example
animation1.duration = 1.0
animation1.fromValue = 1
animation1.toValue = 0
animation1.append(animation1)
var animation2 = CABasicAnimation(keyPath: "key_path_2")
animation2.duration = 1.0
animation2.fromValue = 1
animation2.toValue = 0
// setting beginTime is the key to chaining these
animation2.beginTime = 1.0
animations.append(animation2)
let group = CAAnimationGroup()
group.duration = 2.0
group.repeatCount = FLT_MAX
group.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
group.animations = animations
yourLayer.addAnimation(group, forKey: nil)
你打算做更高級的動畫以及或僅移動,縮放和旋轉(不是3D)? – 2012-07-31 10:28:15
是的,我也使用CATransform3DMakeRotation和其他人 – torhector2 2012-07-31 10:48:25