【问题标题】:Change CAShapeLayer without Animation在没有动画的情况下更改 CAShapeLayer
【发布时间】:2014-03-08 10:37:39
【问题描述】:

我想设置CAShapeLayer 的strokeEnd 属性,没有默认动画,根本没有动画。我环顾四周试图找到如何做到这一点,但一切似乎都是关于如何为属性设置动画。

【问题讨论】:

    标签: objective-c cocoa core-animation calayer


    【解决方案1】:

    在 Core Animations 术语中,动画的更通用术语是“动作”。例如,您可以看到 CAAnimation 符合 CAAction 协议。您还会看到禁用它们(禁用动画)时使用的术语“动作”。

    有许多不同的方法可以改变图层的动作。其中许多在the discussion of the actionForKey: documentation on CALayer 中有很好的记录(摘录如下)。其中一些在子类化时更相关(您还可以在子类中覆盖 actionForKey: 以为新键添加更多隐式操作。

    此方法按以下顺序搜索图层的关联动作:

    1. 如果层有一个委托并且该委托实现了访问层的过滤器方法,层调用该方法。代表必须执行以下操作之一:
      • 返回给定键的操作对象。
      • 如果它不处理该操作,则返回 nil。
      • 如果NSNull 对象不处理该操作,则返回该对象并且应终止搜索。
    2. 图层在图层的actions 字典中查找。
    3. 图层在 `style 字典中查找包含键的操作字典。
    4. 该层调用其 `defaultActionForKey: 方法来查找任何类定义的操作。
    5. 该层查找由 Core Animation 定义的任何隐式操作。

    当您想要禁用动画时,最有趣的两种方法是(两种不同,因为它们用于稍微不同的事情):

    1. 使用 CATransaction 禁用操作(以上未提及)
    2. 为操作字典中的@"strokeEnd" 键设置[NSNull null](上面的数字2)

    禁用操作

    当您暂时想要完全禁用许多不同属性的操作,同时在其他地方仍然有动画时,使用事务来禁用动画是很好的选择。在代码中它看起来像这样:

    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    // change your property here 
    yourShapeLayer.strokeEnd = 0.7;
    [CATransaction commit]; // animations are disabled until here...
    

    更改动作字典

    您可以通过修改图层操作字典来永久更改一个或多个键的默认动画。设置[NSNull null] 意味着不应该有动画并且层应该停止在别处寻找默认动画。您也可以使用它来添加动画属性。使用动作字典删除动画看起来像这样:

    yourShapeLayer.actions = @{@"strokeEnd": [NSNull null]};
    yourShapeLayer.strokeEnd = 0.7; // this won't have an animation
    

    【讨论】:

    • 喜欢这个答案,但它提出了更多问题。因此,这说明(1)如何在显式事务范围内禁用所有层和所有键的动画以进行更改,以及(2)如何永久禁用指定层和键的动画。但是如何只为一次更改禁用指定层和键的动画呢?
    • @algal 是的,我似乎有时会写很长的答案:) 我会说,如果这是一次性的事情,那么交易是最简单的。如果您只希望它应用于一个特定层和一个属性,那么只需在事务范围内更改该层上的该属性。
    【解决方案2】:

    您可以执行以下操作:

    NSDictionary *actions = @{@"strokeEnd": [NSNull null]};
    yourShapeLayer.actions = actions;
    

    这将使它不会为属性设置动画。您还可以通过将其他属性添加到其中来指定不设置动画的其他属性:

    NSDictionary *actions = @{@"strokeEnd": [NSNull null], @"position": [NSNull null], @"position": [NSNull null]};
    

    【讨论】:

      【解决方案3】:

      我认为一个不错的解决方案是创建一个CABasicAnimation(keyPath: "strokeEnd") 并将持续时间设置为非常小的值。这是一个例子:

      let basicAnimation = CABasicAnimation(keyPath: "strokeEnd")
      basicAnimation.toValue = someValue
      basicAnimation.duration = animated ? 2.0 : 0.01
      basicAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
      
      basicAnimation.fillMode = kCAFillModeForwards
      basicAnimation.isRemovedOnCompletion = false
      
      // Apply the animation
      circleProgress.add(basicAnimation, forKey: "progress")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-06-20
        • 1970-01-01
        • 1970-01-01
        • 2023-03-10
        • 2021-09-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多