【问题标题】:animating multiple CALayers, but not in the same time space为多个 CALayer 设置动画,但不在同一时间空间中
【发布时间】:2009-02-18 23:39:37
【问题描述】:

我有几个CALayers,我正在尝试将它们制作成一个新的zPosition,每一层都略微延迟。

每个动画应该花费 0.25 秒,并在上一个动画开始后 0.05 秒开始。在每个动画结束时,该层将从层树中移除。

我已成功使用-animationDidStop:finished: 委托方法在图层完成时删除它们,但我无法正确地对动画进行排序。

是否可以以这种方式安排动画,以及如何安排?

【问题讨论】:

    标签: core-animation


    【解决方案1】:

    我仍然想听听其他人的建议,但我想我已经解决了这个问题。

    我现在正在创建特定的 CAAnimation 对象并指定它们的 beginTime 属性。我之前这样做过,但它不起作用,我终于意识到,要获得 beginTime 属性,必须将动画添加到 CAAnimationGroup

    所以,我的代码如下所示:

    NSArray *layers = /* layers to be animated away */
    CGFloat startOffset = 0.01;
    
    for (NSInteger index = 0; index < layers.count; index++) {
        CALayer *layer = [layers objectAtIndex:index];
    
        CABasicAnimation *zoomOut = [CABasicAnimation animationWithKeyPath:@"zPosition"];
        zoomOut.toValue = [NSNumber numberWithDouble:400.0];
        zoomOut.beginTime = index * startOffset;
    
        CAAnimationGroup *group = [CAAnimationGroup animation];
        group.animations = [NSArray arrayWithObject:zoomOut];
        group.delegate = self;
    
        [layer addAnimation:group forKey:@"zoomAway"];
    }
    

    【讨论】:

    • 我也一直在寻找答案,并尝试了各种不同的东西。我认为可以创建一个所有图层都可以共享的共享 CAAnimationGroup 作为参考时间框架,但这显然行不通。我现在认为这可能是解决问题的方法,但也很想听听其他对此有更深入了解的人。
    【解决方案2】:

    我发现如果您将 BeginTime 属性的值作为 QuartzCore 的 CACurrentMediaTime() 函数返回的值的增量作为基础,那么 BeginTime 属性确实可以工作,而无需将动画放入组中。

    例如anim.beginTime = CACurrentMediaTime() + 0.05;

    【讨论】:

    • 酷。我不记得我最初这样做时尝试过。
    【解决方案3】:

    我希望我有代表发表评论,但是其他一些文档揭示了将 anim.beginTime 设置为 CACurrentMediaTime() 的原因:

    AVCoreAnimationBeginTimeAtZero 使用此常量将 CoreAnimation 的动画 beginTime 属性设置为时间 0。 该常量是一个小的、非零的正值,可防止 CoreAnimation 将 0.0 替换为 CACurrentMediaTime。 在 iOS 4.0 及更高版本中可用。 在 AVAnimation.h 中声明。

    因此,将 beginTime 正常设置为 0 是将其设置为 CACurrentMediaTime() 的简写。所以你可以使用 来错开各个组的开始。

    【讨论】:

    • “所以 beginTime 的正常设置为 0 是设置它为 CACurrentMediaTime() 的简写”,哇,一直在寻找这个解释,非常感谢。
    【解决方案4】:

    斯威夫特 3

    事实证明,您可以通过以下操作相对简单地做到这一点:

    var timeOffset:Double = 0 
    let delay:Double = 0.1
    for layer in layers {
        let a = CABasicAnimation(keyPath: "path"
        a.fromValue = layer.ovalPathSmall.cgPath
        a.toValue = layer.ovalPathLarge.cgPath
        a.fillMode = kCAFillModeForwards
        a.beginTime = CACurrentMediaTime() + timeOffset
        a.duration = 0.3
        a.isRemovedOnCompletion = true
        layer.add(a, forKey: nil)
    
        timeOffset += 0.3 + delay
    } 
    

    所有图层都是 CALayer 或 CAShapeLayer,如果您想知道什么是 obalPathSmall 和ovalPathLarge:

    ovalPathSmall = UIBezierPath(arcCenter: position, radius: smallRadius, startAngle: 0, endAngle: 2 * .pi, clockwise: true)
    ovalPathLarge = UIBezierPath(arcCenter: position, radius: largeRadius, startAngle: 0, endAngle: 2 * .pi, clockwise: true)
    

    【讨论】:

      【解决方案5】:

      感谢您分享您的结果,我还发现如果在没有组的情况下使用 BeginTime 属性将不起作用。

      在我的例子中,如果在 CABasicAnimation 上设置了一些设置,如 BeginTime 和 Duration,则会被忽略,但如果直接设置 CAAnimationGroup,则可以工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-25
        • 1970-01-01
        • 1970-01-01
        • 2016-05-09
        • 1970-01-01
        • 2012-09-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多