ios - 当我在 animationDidStart : 中设置结束值时,CABasicAnimation 不插值

标签 ios objective-c core-animation calayer caanimation

我制作了一个用于紧凑创建 CABasicAnimation 实例的包装器。 它是通过 UIView 的类别作为名为 change:from:to:in:ease:delay:done: 的实例方法实现的。例如,我可以这样做:

[self.logo
  change:@"y"
  from:nil            // Use current self.logo.layer.position.y
  to:@80
  in:1                // Finish in 1000 ms
  ease:@"easeOutQuad" // A selector for a CAMediaTimingFunction category method
  delay:0
  done:nil];

问题

当 CABasicAnimation 启动时,animationDidStart:self.logo.layer.position.y 设置为 80(结束值)。在它像这样工作之前,我尝试使用 animationDidStop:finished: 做同样的事情,但发现动画完成后图层闪烁。 现在,图层直接到达最终值,没有插值发生。我在我的 UIView 类别中实现了 animationDidStart:,如下所示:

- (void)animationDidStart:(CAAnimation *)animation
{
    [self.layer
        setValue:[animation valueForKey:@"toValue"]
        forKeyPath:[animation valueForKey:@"keyPath"]];
}

我正在设置结束值,以便将模型层与表示层相匹配(换句话说,防止重置回起始位置)。

这是 change:from:to:in:ease:delay:done:...

的实现
- (CABasicAnimation*) change:(NSString*)propertyPath
                        from:(id)from
                          to:(id)to
                          in:(CGFloat)seconds
                        ease:(NSString*)easeName
                       delay:(CGFloat)delay
                        done:(OnDoneCallback)done
{
  NSString* keyPath = [app.CALayerAnimationKeyPaths objectForKey:propertyPath];
  if (keyPath == nil) keyPath = propertyPath;
  CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:keyPath];
  if (delay > 0) animation.beginTime = CACurrentMediaTime() + delay;
  if (easeName != nil) animation.timingFunction = [CAMediaTimingFunction performSelector:NSSelectorFromString(easeName)];
  if (from != nil) animation.fromValue = from;
  animation.toValue = to;
  animation.duration = seconds;
  animation.delegate = self;
  [self.layer setValue:done forKey:@"onDone"];
  [self.layer addAnimation:animation forKey:keyPath];
  return animation;
}

在上面代码的第一行,这是我用来将属性快捷方式转换为真正的 keyPath 的 NSDictionary。这样我就可以每次都输入 @"y" 而不是 @"position.y"

app.CALayerAnimationKeyPaths = @{
  @"scale": @"transform.scale",
  @"y": @"position.y",
  @"x": @"position.x",
  @"width": @"frame.size.width",
  @"height": @"frame.size.height",
  @"alpha": @"opacity",
  @"rotate": @"transform.rotation"
};

有什么问题吗?

最佳答案

我认为您看到的是预期的行为。在该属性的动画开始后,您正在设置一个可动画的属性。这实际上是最常见和最推荐的方法来完全按照您所看到的进行操作,即取消动画并立即跳转到最终位置。所以你是在故意取消你自己的动画。

如果这不是您想要的,请不要那样做。只需在动画附加到层之前将动画属性设置为其最终值 - 当然,在这样做时要小心不要触发隐式动画。

关于ios - 当我在 animationDidStart : 中设置结束值时,CABasicAnimation 不插值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22123131/

相关文章:

ios - 如何为 UIButton 创建的自定义背景艺术实现 scale-9(9 切片)

objective-c - cocos2d 改变 Sprite 纹理

ios - 如何禁止 CALayers 响应 HitTest ?

iphone - beginAnimations 和 using animations block 之间的动画速度不同

ios - 替代 performSelector :withObject:afterDelay: for animating views consequantially

cocoa - CATextLayer 中不需要的填充

objective-c - 方法 [[UIDevice currentDevice] uniqueIdentifier] 不再被允许,我需要一个替代方法

iphone - iOS:从网址下载图片并保存在设备中

ios - headerViewForSection 和 footerViewForSection 总是返回 nil

objective-c - 如何以编程方式检测 Mac OS X Server Edition?