【问题标题】:CABasicAnimation is not animating. Help?CABasicAnimation 没有动画。帮助?
【发布时间】:2011-06-26 01:35:28
【问题描述】:

现在,在您焦躁不安之前,我说的是 Cocoa,而不是 Cocoa-Touch。有了这个,让我们开始吧。我最近开始为 Mac 编程。为什么?因为它很酷。你知道什么不酷吗?无法像其他很酷的孩子一样制作精美的动画。我想不通,如果你能帮助我,你会拯救我头上剩下的几根头发。

好的,我有一个NSCollectionView。我花了很长时间才弄清楚这一点,但无论如何。我已经在 Interface Builder 中制作了 NSCollectionView 层支持。我听说这应该使这个神奇的工作。我试着用这个来动画我的收藏视图:

//usersView is my NSCollectionView
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"];    
CATransform3D scale = CATransform3DMakeScale(2.0, 2.0, 0.0);
[anim setFromValue:[NSValue valueWithCATransform3D:CATransform3DIdentity]];
[anim setToValue:[NSValue valueWithCATransform3D:scale]];
[anim setDuration:1.0f];
[[usersView layer] addAnimation:anim forKey:nil];
[[usersView layer] setTransform:scale];

现在是这样:它确实改变了视图,但没有一个很酷的动画。我也试过这个:

[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
[CATransaction setValue:[NSNumber numberWithFloat:3.0f] forKey:kCATransactionAnimationDuration];
[usersView layer].transform = CATransform3DMakeScale(2.0, 2.0, 0.0);
[CATransaction commit];

没有骰子。我相信我需要帮助。谢谢。

【问题讨论】:

  • NSCollectionView 的超级视图是否也有图层支持?
  • @Rob:superview 是指包含NSCollectionView 的视图吗?不,这不对。原因是因为它是一个透明的窗口,我不希望视图是丑陋的灰色。

标签: objective-c cocoa macos core-animation layer


【解决方案1】:

我相信,对于尝试隐含动画的第二段代码(通过为transform 属性分配新值),您需要跳过将kCATransactionDisableActions 属性设置为true,因为实际上是说 不要为过渡设置动画(这与您的意图完全相反)。明确地说,您可以将该属性设置为 false. 也可能很容易出现其他问题;在编码和运行之前,我似乎永远不知道确切需要什么。 (通过核心动画,我总是发现自己一点一点地朝着我想要的结果前进。但在终于至少获得动画效果后,它真的激励我继续调整代码,直到它按我想要的方式工作它!,即核心动画并不容易上手。)

至于第一个问题,显式动画,我相信一个问题与您设置图层变换属性的最后一行有关;我会先把它排除在外(尽管从长远来看,它可能必须在其他地方重新解决)。设置该变换立即将图层更改为动画完成后的外观(这就是您看到变换立即发生的原因),但这并不能完全解释自事务(代码完成后开始)后没有看到任何动画,即在发生立即转换之后)确实具有“开始”和“结束”值。首先,我会先找到一些执行类似动画的示例代码,然后逐段更改以获得您想要的。 (这就是我在尝试完全自己编写动画并失败后学会使用核心动画的方法;确实花了很长时间才把它做好,但这样做我真的感觉更好。)你也可以想回到文档并真正尝试了解core animation rendering architecture 的概念,即 layer-tree、presentation-tree渲染树 以及在动画的不同阶段显示的内容以及如何影响它(这实际上只会在经过大量的试验和错误后才真正沉入其中)。坚持下去,直到有意义为止!

【讨论】:

  • 感谢您花时间写下所有这些。很棒的信息。谢谢!
【解决方案2】:

你可能想使用

[usersView setWantsLayer:YES];

如果你发现你的层是零。默认情况下,所有视图都没有图层。

【讨论】:

    【解决方案3】:

    经过几次尝试,我终于可以制作动画了。有几件事需要注意。

    如果您希望将变换锚定在中心,那么您应该在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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-27
      • 1970-01-01
      • 1970-01-01
      • 2011-03-14
      • 2011-08-28
      • 2010-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多