tl;dr: 非常容易误用removeOnCompletion = NO
,大多数人没有意识到这样做的后果。正确的解决方法是真正更改模型值。
首先,我并不想评判或针对你。我一遍又一遍地看到同样的误解,我也理解为什么会发生这种情况。通过解释“为什么”事情会发生,我希望每个经历过同样问题并看到这篇答案的人能够更多地了解他们的代码正在做什么。
出了什么问题
我认为animation.additive = YES;
会导致进一步的动画使用当前状态作为起点。
那非常正确,这正是发生的事情。在这方面,电脑很有趣。它们总是按照你所“告诉”的方式执行,而不是按照你所“期望”的方式执行。
removeOnCompletion = NO
可能会造成麻烦
在你的情况下,罪魁祸首是这条代码:
animation.removedOnCompletion = NO
通常情况下,人们会误用动画来保留动画完成后的最终值。唯一的问题是通过不从视图中移除动画来实现这一点。核心动画中的动画不会改变它们正在动画的底层属性,它们只是在屏幕上对其进行动画处理。如果您在动画过程中查看实际值,则永远不会看到它发生改变。相反,动画处理的是所谓的呈现层。
通常情况下,当动画完成时,它会从图层中移除,并且呈现层消失,模型层再次出现在屏幕上。但是,当您将动画附加到图层时,屏幕上的所有内容看起来都应该如此,但是您引入了一个差异,即属性所表示的转换方式与图层在屏幕上旋转的方式之间存在差异。
当您将动画配置为可添加时,这意味着要向现有值中“添加”from和to值,就像您所说的那样。问题在于该属性的值为0。您永远不会改变它,只是对其进行动画处理。下次尝试将该动画添加到同一图层时,该值仍然不会更改,但是动画正在按照其配置执行:“从模型的当前值开始添加动画”。
解决方案是跳过那行代码。结果是旋转不会保留。使其保留的更好方法是更改模型。在对旋转进行动画处理之前设置旋转的新结束值,以便在删除动画时模型看起来与应该看起来的一样。
有一个非常方便的
CABasicAnimation
属性(我将使用它)称为
byValue
,可用于执行相对动画。可以将其与
toValue
和
fromValue
组合使用以执行许多不同类型的动画。这些不同的组合都在其文档中指定(在该部分下)。我要使用的组合是:
byValue
和 toValue
都是非空的。在(toValue - byValue)
和toValue
之间插入。
通过显式设置
toValue
为0,动画将从“currentValue-byValue”到“current value”进行处理。通过首先更改模型,当前值即为最终值。
一些实际代码:
NSString *zRotationKeyPath = @"transform.rotation.z";
CGFloat currentAngle = [[_myview.layer valueForKeyPath:zRotationKeyPath] floatValue];
CGFloat angleToAdd = M_PI_2;
[_myview.layer setValue:@(currentAngle+angleToAdd) forKeyPath:zRotationKeyPath];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:zRotationKeyPath];
animation.duration = 10;
animation.toValue = @(0.0);
animation.byValue = @(angleToAdd);
[_myview.layer addAnimation:animation forKey:@"90rotation"];
免责声明:
我没有运行过这段代码,但相当确定它应该可以正常运行,并且我没有打错任何字。如果有错误,请纠正我。整个讨论仍然有效。