删除 CALayer 内容属性的插值
Posted
技术标签:
【中文标题】删除 CALayer 内容属性的插值【英文标题】:Remove Interpolation of CALayer's contents property 【发布时间】:2010-12-02 11:16:23 【问题描述】:重新提问:
当您为 contents 键添加动画时,显然会触发 CATransitionAnimation 将原始内容属性淡化为动画值数组中的第一个值,从而导致 0.25 秒的淡化。而且看起来很糟糕!我使用此处讨论的所有方法(通过委托将空动画返回到动作字典中,使用 CATransaction)抑制了每个可动画属性,但这些似乎都不是针对这个特定的过渡动画。
我一直在研究可能导致此问题的财产,但无法弄清楚。
当您向内容键添加动画时,我需要抑制正在发生的过渡动画。
由于我很茫然,我将正在添加的关键帧动画给你看。我想也许我在这里做错了什么?请注意,该数组只是一个包含 6 个 CGImageRef(动画帧)的数组。
+ (CAKeyframeAnimation *)moveLeftAnimation
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
animation.values = [NSArray arrayWithArray:[Setzer walkingLeftSprite]];
animation.duration = 0.5f;
animation.keyTimes = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.0],
[NSNumber numberWithFloat:0.2],
[NSNumber numberWithFloat:0.4],
[NSNumber numberWithFloat:0.6],
[NSNumber numberWithFloat:0.8],
[NSNumber numberWithFloat:1.0],
nil];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
return animation;
另外,我在精灵的动作字典中有一个处理位置键的动画:
+ (CABasicAnimation *)moveAnimation
CABasicAnimation *moveAnimation = [CABasicAnimation animation];
moveAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
moveAnimation.duration = 0.5f;
return moveAnimation;
我在想,当您更改图层的位置时,可能会发生这种过渡?我不知道...
请帮忙!这让我发疯了!
【问题讨论】:
+1 在这篇文章和上一篇文章之间无偿使用 Setzer 我已经对我添加的两个动画进行了交易(我明确添加的关键帧动画,并且在它的动作字典中有一个位置键,它只是使移动线性并且也是 0.5 秒)但它不会抑制上面屏幕截图中明显的 CATransitionAnimation 。那就是问题所在。这是我对简单英语的尝试:“关键帧动画本身迭代了我从精灵的 gif 中提取的 6 个 CGImageRef,超过 0.5 秒。”哈哈,对不起:( 【参考方案1】:您可以按照我在this answer 中描述的方式进行操作,通过在该层的actions
字典中设置适当的值来禁用各种层属性的隐式动画。
在你的情况下,我相信类似
NSMutableDictionary *newActions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
[NSNull null], @"contents",
nil];
layer.actions = newActions;
[newActions release];
应该阻止图层的contents
属性的隐式动画,直到您明确为它设置动画。
【讨论】:
我对所有答案都投了赞成票,并用代码和图像重新编写了问题。你能再看看我的问题是否更有意义? @Alec - 您正在使用线性计时函数在您的第一个 CAKeyframeAnimation 中明确地为contents
属性设置动画。这将覆盖此处讨论的任何方法,这些方法都只抑制隐式动画(除了 Joe 的第一个建议,它将禁用任何类型的所有动画)。结果将是各种图像之间的线性淡入淡出。
@Alec - 为了达到您想要的效果,您需要像 Joe 建议的那样在 UIImageView 中使用 animationImages
数组,或者创建一个手动定时函数来交换定期取出一个层的内容(结合我上面展示的动作字典方法)。
我试试手动计时功能。顺便说一句,我最终接受了答案:D 我感谢大家对此的帮助。 CoreAnimation 乍一看很简单,因为幕后发生了很多事情。
@Alec - 是的,Core Animation 免费为您提供了很多,甚至在这样的边缘情况下也能很好地支撑。考虑一下,可能仍然有一种方法可以与 Core Animation 的计时机制联系起来,就像 Tim Wood 在这里建议的那样:omnigroup.com/blog/entry/Animating_CALayer_content,但我自己还没有做过这样的事情。【参考方案2】:
为了防止任何动画,您可以将一个对象设置为您的CALayer
的委托,然后实现‑actionForLayer:forKey:
委托方法并返回一个空对象:
- (id<CAAction>)actionForLayer:(CALayer*)layer forKey:(NSString*)key
if(layer == yourLayer)
if([key isEqualToString:@"contents"])
return (id<CAAction>)[NSNull null];
return nil;
【讨论】:
我会试一试。这不会干扰显式添加动画吗? 不,不应该。如果您需要更多地控制哪些层或在哪些状态下不需要动画,只需在委托方法中添加逻辑即可。 它仍然在原始内容属性和动画的第 1 帧之间进行插值。我尝试在委托和操作字典中添加空动画。没有任何效果。 我对所有答案都投了赞成票,并用代码和图像重新编写了问题。你能再看看我的问题是否更有意义?【参考方案3】:这里有一些关于如何解决这个难题的注释,以及每个人的答案如何提供了一个难题。
重申问题:当我向 CALayer 的 @contents
键添加关键帧动画时,原始内容属性和关键帧动画的第一帧之间似乎有 0.25 秒的淡入淡出过渡。这看起来很糟糕,我想摆脱它。
起初,我确信通过使用 CATransaction 可以抑制这种隐式过渡动画,因为这是 Apple 的文档让您相信的。使用交易,我以你能想象到的一切可能的方式压制,但它仍在发生。然后我尝试通过字典为每个动画属性返回 NULL 动画。没运气。然后我做了同样的事情,但有一个代表。还是没有运气。
我没有提到的是,在添加动画和移动图层的同时,它下面的两个子图层正在从它们的超图层中删除。我尝试为 onOrderOut 键添加自定义动画,但无济于事。然后我在 *** 上偶然发现了另一个问题,关于为 onOrderOut 键添加自定义动画。事实证明,很简单,你不能,如果你想在子层被删除时实现一些其他动画,你必须使用 delagate 方法 animationDidStop。 How can I use custom animations for onOrderOut in Core Animation?
所以在这一点上,我确信这个幻影图像与所讨论的实际层无关,即精灵本身。为了测试这一点,我只是没有添加它下面的子层。果然,当我移动精灵时,并没有挥之不去的幽灵。它看起来很完美。然后我添加了下面的图层,那里是幽灵。就好像精灵的内容被绘制到了它下面的图层中,所以当它们被移除时,就会有一种印记。
我没有删除子层,而是尝试隐藏它们。答对了。它是完美的。发生了相同的淡入淡出过渡,但没有留下精灵的印记。我还是不明白为什么会这样。
然后,因为我还需要移除这些层,所以我为精灵的各种运动动画实现了 animationDidStop 委托方法来移除它们。
这是原文:
这是新版本:
因此,虽然从技术上讲,我不明白为什么会出现印记,但我几乎可以肯定,这与删除子图层时幕后发生的事情有关。另外,出于兴趣,我仍然希望在动画开始时隐藏该子图层,所以我只是将其设置为隐藏并提供了我自己的过渡动画。
感谢大家的帮助。这是一个奇怪的用例,我知道,但如果你曾经想过制作一个基于 2d 精灵的最终幻想战术,那么希望我的痛苦对你有好处!
【讨论】:
【参考方案4】:class AnimationLayer: CALayer
override class func defaultAction(forKey event: String) -> CAAction?
let transition = CATransition()
transition.duration = 0
return transition
【讨论】:
以上是关于删除 CALayer 内容属性的插值的主要内容,如果未能解决你的问题,请参考以下文章
CALayer 的 position和anchorPoint属性