动画完成后 CABasicAnimation 重置为初始值
我正在旋转 CALayer 并尝试在动画完成后将其停止在最终位置。
但动画完成后,它会重置到初始位置。
(xcode 文档明确指出动画不会更新属性的值。)
有关如何实现此目的的任何建议。
I am rotating a CALayer and trying to stop it at its final position after animation is completed.
But after animation completes it resets to its initial position.
(xcode docs explicitly say that the animation will not update the value of the property.)
any suggestions how to achieve this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
returnedOnCompletion 的问题是 UI 元素不允许用户交互。
我的技术是在动画中设置 FROM 值,在对象上设置 TO 值。
动画将在开始之前自动填充 TO 值,并且当它被删除时将使对象保持正确的状态。
The problem with removedOnCompletion is the UI element does not allow user interaction.
I technique is to set the FROM value in the animation and the TO value on the object.
The animation will auto fill the TO value before it starts, and when it's removed will leave the object at it's correct state.
核心动画维护两层层次结构:模型层和表示层。当动画进行时,模型层实际上是完整的并保持其初始值。默认情况下,动画一旦完成就会被删除。然后表示层回落到模型层的值。
只需将
removedOnCompletion
设置为NO
就意味着动画不会被删除并浪费内存。此外,模型层和表示层将不再同步,这可能会导致潜在的错误。所以直接将模型层的属性更新为最终值会是一个更好的解决方案。
如果上面代码第一行引起了隐式动画,请尝试关闭if:
Core animation maintains two layer hierarchies: the model layer and the presentation layer. When the animation is in progress, the model layer is actually intact and keeps it initial value. By default, the animation is removed once the it's completed. Then the presentation layer falls back to the value of the model layer.
Simply setting
removedOnCompletion
toNO
means the animation won't be removed and wastes memory. In addition, the model layer and the presentation layer won't be synchronous any more, which may lead to potential bugs.So it would be a better solution to update the property directly on the model layer to the final value.
If there's any implicit animation caused by the first line of above code, try to turn if off:
设置以下属性:
Set the following property:
当您将
CABasicAnimation
添加到图层时,您只需将其关键点设置为position
即可。通过这样做,它将覆盖在运行循环中当前通道的位置上完成的隐式动画。您可以了解更多有关 2011 Apple WWDC 视频会议 421 - 核心动画要点(视频中间)的信息
You can simply set the key of
CABasicAnimation
toposition
when you add it to the layer. By doing this, it will override implicit animation done on the position for the current pass in the run loop.You can have more information on 2011 Apple WWDC Video Session 421 - Core Animation Essentials (middle of the video)
这是可行的:
核心动画在动画过程中在普通层之上显示一个“表示层”。因此,将不透明度(或其他)设置为您希望在动画完成且表示层消失时看到的内容。在添加动画之前执行此操作,以避免动画完成时出现闪烁。
如果您想要延迟,请执行以下操作:
最后,如果您使用“removedOnCompletion = false”,它将泄漏 CAAnimations,直到该层最终被处置 - 避免。
This works:
Core animation shows a 'presentation layer' atop your normal layer during the animation. So set the opacity (or whatever) to what you want to be seen when the animation finishes and the presentation layer goes away. Do this on the line before you add the animation to avoid a flicker when it completes.
If you want to have a delay, do the following:
Finally, if you use 'removedOnCompletion = false' it'll leak CAAnimations until the layer is eventually disposed - avoid.
只需将其放入您的代码中即可
just put it inside your code
CALayer 具有模型层和表示层。在动画期间,表示层独立于模型进行更新。动画完成后,表示层将使用模型中的值进行更新。如果您想避免动画结束后出现不和谐的跳跃,关键是保持两层同步。
如果知道最终值,则可以直接设置模型。
但是,如果您有一个不知道结束位置的动画(例如,用户可以暂停然后反转的缓慢淡入淡出),那么您可以直接查询表示层以查找当前值,然后更新模型。
从表示层提取值对于缩放或旋转键路径也特别有用。 (例如
transform.scale
、transform.rotation
)A CALayer has a model layer and a presentation layer. During an animation, the presentation layer updates independently of the model. When the animation is complete, the presentation layer is updated with the value from the model. If you want to avoid a jarring jump after the animation ends, the key is to keep the two layers in sync.
If you know the end value, you can just set the model directly.
But if you have an animation where you don't know the end position (e.g. a slow fade that the user can pause and then reverse), then you can query the presentation layer directly to find the current value, and then update the model.
Pulling the value from the presentation layer is also particularly useful for scaling or rotation keypaths. (e.g.
transform.scale
,transform.rotation
)所以我的问题是我试图通过平移手势旋转一个对象,所以每次移动时我都会有多个相同的动画。我有
fillMode = kCAFillModeForwards
和isRemovedOnCompletion = false
但它没有帮助。就我而言,我必须确保每次添加新动画时动画关键点都不同:So my problem was that I was trying to rotate an object on pan gesture and so I had multiple identical animations on each move. I had both
fillMode = kCAFillModeForwards
andisRemovedOnCompletion = false
but it didn't help. In my case, I had to make sure that the animation key is different each time I add a new animation:在不使用
removedOnCompletion
的情况下,您可以尝试以下技术:
Without using the
removedOnCompletion
You can try this technique:
简单地设置
fillMode
和removedOnCompletion
对我来说不起作用。我通过将下面的所有属性设置为 CABasicAnimation 对象解决了这个问题:此代码将
myView
转换为其大小的 85%(第三维不变)。Simply setting
fillMode
andremovedOnCompletion
didn't work for me. I solved the problem by setting all of the properties below to the CABasicAnimation object:This code transforms
myView
to 85% of its size (3rd dimension unaltered).@Leslie Godwin 的回答不太好,“self.view.layer.opacity = 1;”立即完成(大约需要一秒),如果您有疑问,请将 alphaAnimation.duration 修复为 10.0。
你必须删除这一行。
因此,当您将 fillMode 固定为 kCAFillModeForwards 并将removedOnCompletion 固定为 NO 时,您可以让动画保留在图层中。如果您修复动画委托并尝试以下操作:
...执行此行时图层会立即恢复。这是我们想要避免的。
您必须先修复图层属性,然后才能从中删除动画。试试这个:
@Leslie Godwin's answer is not really good, "self.view.layer.opacity = 1;" is done immediately (it takes about one second), please fix alphaAnimation.duration to 10.0, if you have doubts.
You have to remove this line.
So, when you fix fillMode to kCAFillModeForwards and removedOnCompletion to NO, you let the animation remains in the layer. If you fix the animation delegate and try something like:
...the layer restores immediately at the moment you execute this line. It's what we wanted to avoid.
You must fix the layer property before remove the animation from it. Try this:
最简单的解决方案是使用隐式动画。这将为您处理所有这些麻烦:
如果您想自定义例如持续时间,您可以使用 NSAnimationContext :
注意:这仅在 macOS 上进行了测试。
我最初在执行此操作时没有看到任何动画。问题是视图支持的图层不隐式动画。要解决此问题,请确保您自己添加一个图层(在将视图设置为图层支持之前)。
如何执行此操作的一个示例是:
使用 self.wantsLayer 在我的测试中没有产生任何差异,但它可能会产生一些我不知道的副作用。
The easiest solution is to use implicit animations. This will handle all of that trouble for you:
If you want to customize e.g. the duration, you can use
NSAnimationContext
:Note: This is only tested on macOS.
I initially did not see any animation when doing this. The problem is that the layer of a view-backed layer does not implicit animate. To solve this, make sure you add a layer yourself (before setting the view to layer-backed).
An example how to do this would be:
Using
self.wantsLayer
did not make any difference in my testing, but it could have some side effects that I do not know of.似乎将removedOnCompletion 标志设置为 false 并将 fillMode 设置为 kCAFillModeForwards 对我来说也不起作用。
在图层上应用新动画后,动画对象将重置为其初始状态,然后从该状态开始动画。
另外还需要做的是在设置新动画之前根据其表示层的属性设置模型层所需的属性,如下所示:
It seems that removedOnCompletion flag set to false and fillMode set to kCAFillModeForwards doesn't work for me either.
After I apply new animation on a layer, an animating object resets to its initial state and then animates from that state.
What has to be done additionally is to set the model layer's desired property according to its presentation layer's property before setting new animation like so:
这是来自 Playground 的示例:
false
设置为isRemovedOnCompletion
- 让核心动画在动画完成后清理Here is a sample from playground:
false
toisRemovedOnCompletion
- let Core Animation clean after the animation is finished这就是答案,它是我的答案和克里希南的答案的结合。
默认值为
kCAFillModeRemoved
。 (这是您看到的重置行为。)Here's the answer, it's a combination of my answer and Krishnan's.
The default value is
kCAFillModeRemoved
. (Which is the reset behavior you're seeing.)