经过几次尝试,我终于可以制作动画了。有几件事需要注意。
如果您希望将变换锚定在中心,那么您应该在CALayer: 上调用anchorPoint 在将视图添加到其父视图!否则子视图将从anchorPoint 位置开始被裁剪。
CALayer *layer = _completionIndicator.layer;
layer.anchorPoint = CGPointMake(.5, .5);
将动画调用包装在 runAnimationGroup 块中(_completionIndicator 是定义为 NSView 的属性,centerInSuperview 定义如下):
[self.contentView addSubview:_completionIndicator];
[_completionIndicator centerInSuperview];
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
CGFloat duration = <#duration#>;
CALayer *layer = _completionIndicator.layer;
CABasicAnimation *animation;
//Transform
animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(<#scale#>, <#scale#>, 1.0)];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
[animation setDuration:duration];
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
[layer addAnimation:animation forKey:@"zoomIn"];
//Fade
animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue = [NSNumber numberWithFloat:0.0];
animation.toValue = [NSNumber numberWithFloat:1.0];
[animation setDuration:duration];
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
[layer addAnimation:animation forKey:@"fadeIn"];
} completionHandler:^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
[NSThread sleepForTimeInterval:<#seconds#>];
dispatch_sync(dispatch_get_main_queue(), ^{
[self hideCompletionIndicator];
});
});
}];
设置fillMode 对于流畅的动画至关重要。默认为kCAFillModeRemoved,第一次运行后运行动画时会导致跳转。
在 OSX 10.11 上,不需要在 NSView 上设置 wantsLayer。我不知道以前的版本。
要隐藏视图,只需执行相反的操作,并在完成块中删除视图:
- (void) hideCompletionIndicator
{
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
CGFloat duration = <#duration#>;
CALayer *layer = _completionIndicator.layer;
CABasicAnimation *animation;
//Transform
animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(<#scale#>, <#scale#>, 1.0)];
[animation setDuration:duration];
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
[layer addAnimation:animation forKey:@"zoomOut"];
//Fade
animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue = [NSNumber numberWithFloat:1.0];
animation.toValue = [NSNumber numberWithFloat:0.0];
[animation setDuration:duration];
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
[layer addAnimation:animation forKey:@"fadeOut"];
} completionHandler:^{
[_completionIndicator removeFromSuperview];
}];
}
NSView 类别实现
@implementation NSView (Additions)
- (void) centerInSuperview
{
[self centerInView:[self superview]];
}
- (void) centerInView:(NSView *)otherView
{
int w = self.frame.size.width;
int h = self.frame.size.height;
int x = (otherView.frame.size.width - w)/2;
int y = (otherView.frame.size.height - h)/2;
self.frame = NSMakeRect(x, y, w, h);
}
@end
NSView 分类界面
@interface NSView (Additions)
- (void) centerInSuperview;
- (void) centerInView:(NSView *)otherView;
@end