我刚创建了一个像这样的关键帧动画:
[UIView animateKeyframesWithDuration:10 delay:0 options:0 animations:^{
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:.1 animations:^{
view.alpha = 0;
}];
} completion:nil];
这是创建的CAKeyframeAnimation
:
(lldb) po [self.layer animationForKey:@"opacity"]
<CAKeyframeAnimation:0x10a6364b0; keyTimes = (
0,
"0.1",
1
); values = (
1,
0,
0
); calculationMode = linear; delegate = <UIViewKeyframeAnimationState: 0x10a6358d0>; fillMode = both; timingFunction = easeInEaseOut; duration = 10; keyPath = opacity>
问题:
整个动画需要10秒钟,不透明度动画为10 * 0.1 = 1秒,对吧?当我查看动画时,更改的动画方式超过1秒。
为什么?
答案 0 :(得分:8)
原因是动画的计时功能不是线性的。
“时间和空间是相对的概念。” - 相对论
图层和动画使用分层计时系统,其中每个对象都有自己的本地时间,这取决于其父项和自己的计时参数。
例如,动画具有定义其起搏的定时功能。 UIKit创建的动画的默认计时功能是缓入缓出计时功能,它定义了一个缓慢开始的计时,在其持续时间的中间加速,然后在完成之前再次减速。它使得平滑的动画不会突然开始或停止。然而,当你需要精确的计时时,你的关键帧动画的关键时间也会变得很糟糕。
您可以通过将UIViewAnimationOptionCurveLinear
选项传递给animateKeyframesWithDuration:delay:options:animations:completion:
方法来停用缓入缓出时间。我不确定是否需要将值从UIViewAnimationOptions
转换为UIViewKeyframeAnimationOptions
并且文档没有说明任何内容。也许更好(但更详细)的方法是将关键帧动画块嵌入标准动画块中,如下所示:
[UIView animateWithDuration:10 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
[UIView animateKeyframesWithDuration:0 /*inherited*/ delay:0 options:0 animations:^{
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:.1 animations:^{
view.alpha = 0;
}];
} completion:nil];
} completion:nil];