【发布时间】:2014-03-02 02:28:59
【问题描述】:
我已经为 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 objective-c core-animation calayer caanimation