Objective c 链接核心动画
在核心动画环境中,哪种最优雅、最模块化的动画链接方式 我的意思是在其他动画刚完成时开始制作动画(例如,更改Objective c 链接核心动画,objective-c,cocoa,core-animation,Objective C,Cocoa,Core Animation,在核心动画环境中,哪种最优雅、最模块化的动画链接方式 我的意思是在其他动画刚完成时开始制作动画(例如,更改位置,然后更改不透明度)。。通常的方法是直接更改属性: layer.position = new_point; layer.opacity = 0.0f; 但这同时也会起作用。我想让一个等待另一个 那么如何为不同的对象链接动画呢?我读过关于CATransaction的文章,比如: [CATransaction begin] layer1.property = new_property; [
位置
,然后更改不透明度
)。。通常的方法是直接更改属性:
layer.position = new_point;
layer.opacity = 0.0f;
但这同时也会起作用。我想让一个等待另一个
那么如何为不同的对象链接动画呢?我读过关于CATransaction
的文章,比如:
[CATransaction begin]
layer1.property = new_property;
[CATransaction begin]
layer2.property2 = new_property2;
[CATransaction commit];
[CATransaction commit];
但它似乎不起作用。我不相信您可以像示例中那样“嵌套”CA动画
您需要为动画指定一个代理,并将第二个“过渡”放在代理的animationDidStop:finished:
选择器中
可能想看看苹果的。您还可以使用动画分组和动画的开始时间字段。试着这样做:
CABasicAnimation *posAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
[posAnimation setFromValue:[NSNumber numberWithFloat:0.0]];
[posAnimation setToValue:[NSNumber numberWithFloat:1.0]];
// Here's the important part
[posAnimation setDuration:10.0];
[posAnimation setBeginTime:0.0];
CABasicAnimation *borderWidthAnimation = [CABasicAnimation animationWithKeyPath:@"borderWidth"];
[borderWidthAnimation setFromValue:[NSNumber numberWithFloat:0.0]];
[borderWidthAnimation setToValue:[NSNumber numberWithFloat:1.0]];
// Here's the important part
[borderWidthAnimation setDuration:10.0];
[borderWidthAnimation setBeginTime:5.0];
CAAnimationGroup *group = [CAAnimationGroup animation];
[group setDuration:10.0];
[group setAnimations:[NSArray arrayWithObjects:posAnimation, borderWidthAnimation, nil]];
[layer addAnimation:group forKey:nil];
CAAnimation *a = ...
CAAnimation *b = ...
CAAnimation *c = ...
a.completionHandler = ^{
[self.layer addAnimation:b forKey:@"foo"];
[self.layer addAnimation:c forKey:@"bar"];
};
请注意,整个动画的持续时间为10秒。第一个从第二个0开始,第二个从5秒开始。正如马特所指出的,可以创建动画组,该组由同一层的不同动画组成,具有不同的开始时间。您还可以为独立的
CAAnimation
对象或CAAnimation
组设置代理,当每个动画完成时,它将调用animationDidStop:finished:
代理方法(请注意,组中的动画不会调用其代理的animationDidStop:finished:
方法)
我想出了一个很酷的技巧,使使用CAAnimation animation didstop:finished:
方法更强大。我使用方法setValue:forKey:
向独立动画或动画组添加代码块,并使用@“animationCompletionBlock”键然后,我编写了一个常规的animationDidStop:finished:
方法,用于检查刚刚完成的动画是否有@“animationCompletionBlock”键,如果找到了,则在那里执行代码块
查看github上的这个项目,了解该技术的一个工作示例:
还可以在中设置一组动画
[CATransaction begin];
//...
[[CATransaction commit];
块,正如您所建议的。当您这样做时,您可以使用
CATransaction
类方法setCompletionBlock:
在当前事务组中的所有动画完成时调用一个代码块。然后,一个事务的完成块可以触发下一个事务。我一直喜欢的是s分别设置每个动画的开始和结束时间如下:
我使用了一个DynamicDelegate(它的开发现在正在-Repo中进行,谁知道为什么没有包括我的“工具链”上的所有“技巧”,这个例子不是直接复制/复制的…但是它确实展示了一个非常简单的“链接”动画策略
CATransform3D trans = m34(); // define chain-wide constants.
// Name your "stack". My "nextObject" returns arr[i]->done == nil.
NSArray *layerStack = layer.sublayers;
//define a block, that "takes" a layer as it's argument.
void(^__block ChainBlock)(CALayer*) = ^(CALayer *m) {
// animations, transforms, etc for each inividual "step".
[m animate:@"transform"
// These are just NSValue-wrapped CAT3D's
from:AZV3d(CATransform3DRotate(trans, 0,1,0,0))
to:AZV3d(CATransform3DRotate(trans,1.5,1,0,0))
time:2 // total time == each step * layerStack.count
eased:kCAMediaTimingFunctionEaseOut
completion:^{ // In completion, look for "next" layer.
CAL* m2 = [layers nextObject];
// If there is "another" layer, call this block, again... with it.
if (m2) chainAnis(m2);
// Otherise,you're done. Cleanup, toggle values, whatevs.
else self.finishedProperty = YES;
}];
};
// Give the block we just defined your "first" layer.
ChainBlock(layerStack[0]); // It will recursively feed itself.
这显然取决于一些“外部魔法”,但概念很简单,并且消除了(通过依赖关系)“处理”的需要任何类型的总授权。特别是
动画:从:到:时间:放松:完成
,等等。类别来自伟大。我使用setCompletionBlock
方法定义一个闭包,在第一个动画完成时触发下一个动画:
[CATransaction begin]
layer1.property = new_property;
CATransaction.setCompletionBlock {
[CATransaction begin]
layer2.property2 = new_property2;
[CATransaction commit];
}
[CATransaction commit];
请注意,这很好,但仅适用于应用于单个层的动画。此外,如果要在第一个动画完成后立即调用方法,则不能。仅当整个组完成时才会调用animationDidStop。关键点路径
“位置”
是一个CGPoint
,需要使用NSValue
进行编码(而不是NSNumber
)。