我使用CABasicAnimation
移动和调整图像视图。 我想要的图像视图被添加到上海华,动画,然后从上海华除去。
为了做到这一点,我听我的委托调用CAAnimationGroup
,并且只要它被称为我删除从上海华图像视图。
的问题是,有时在图像中的初始位置闪烁从上海华被去除之前。 什么是避免这种情况的最好方法是什么?
CAAnimationGroup *animGroup = [CAAnimationGroup animation];
animGroup.animations = [NSArray arrayWithObjects:moveAnim, scaleAnim, opacityAnim, nil];
animGroup.duration = .5;
animGroup.delegate = self;
[imageView.layer addAnimation:animGroup forKey:nil];
当您添加一个动画层,动画不改变层的性能。 相反,系统会创建层的副本。 原来层称为模型层,并重复被称为表现层。 表示层的属性改变作为动画的进展,但该模型层的性质保持不变。
当您删除的动画,系统破坏了表示层,只留下模型层,然后在模型层的特性控制层的绘制。 所以,如果模型层的特性不匹配的表现层的属性的最终动画值,该层将立即恢复到动画之前它的外观。
为了解决这个问题,你需要设置模型层的属性,以动画的最终值, 然后将动画添加到该层。 你想这样做的顺序,因为改变图层属性可以为属性,它会跟你要明确添加动画冲突添加一个隐含的动画。 你要确保你的动画明确覆盖隐式动画。
那么,你如何做到这一切的? 基本配方如下:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.fromValue = [NSValue valueWithCGPoint:myLayer.position];
layer.position = newPosition; // HERE I UPDATE THE MODEL LAYER'S PROPERTY
animation.toValue = [NSValue valueWithCGPoint:myLayer.position];
animation.duration = .5;
[myLayer addAnimation:animation forKey:animation.keyPath];
我没有使用过的动画组,所以我不知道你可能需要改变什么。 我只是单独添加的每个动画层。
我也觉得它更容易使用的+[CATransaction setCompletionBlock:]
方法来设置完成处理的一个或几个动画,而不是试图用动画的委托。 您可以设置交易的完成方块,然后添加动画:
[CATransaction begin]; {
[CATransaction setCompletionBlock:^{
[self.imageView removeFromSuperview];
}];
[self addPositionAnimation];
[self addScaleAnimation];
[self addOpacityAnimation];
} [CATransaction commit];
CAAnimations自动完成时删除。 有一个属性removedOnCompletion
控制这一点。 你应该设置到NO
。
此外,有一些被称为fillMode
这之前,其持续时间后,控制动画的行为。 这是声明的属性CAMediaTiming
(其中CAAnimation
符合)。 你应该将其设置为kCAFillModeForwards
。
与这两个变化的动画应该坚持它完成之后。 不过,我不知道你是否需要更改这些对本集团或对本集团,或两者中的各个动画。
继承人在斯威夫特的例子,可以帮助别人
这是一个梯度层上的动画。 它的动画的.locations
财产。
临界点为@robMayoff答案解释完全是:
出人意料的是,当你做一个层的动画,你居然设置终值,第一,启动动画前!
下面是因为动画无休止地重复一个很好的例子。
当动画重复不休,你会看到偶尔动画之间的“闪”,如果你犯的典型错误“忘记你制作动画之前设定的值!”
var previousLocations: [NSNumber] = []
...
func flexTheColors() { // "flex" the color bands randomly
let oldValues = previousTargetLocations
let newValues = randomLocations()
previousTargetLocations = newValues
// IN FACT, ACTUALLY "SET THE VALUES, BEFORE ANIMATING!"
theLayer.locations = newValues
// AND NOW ANIMATE:
CATransaction.begin()
// and by the way, this is how you endlessly animate:
CATransaction.setCompletionBlock{ [weak self] in
if self == nil { return }
self?.animeFlexColorsEndless()
}
let a = CABasicAnimation(keyPath: "locations")
a.isCumulative = false
a.autoreverses = false
a.isRemovedOnCompletion = true
a.repeatCount = 0
a.fromValue = oldValues
a.toValue = newValues
a.duration = (2.0...4.0).random()
theLayer.add(a, forKey: nil)
CATransaction.commit()
}
以下信息可能有助于澄清一些新的程序员。 需要注意的是在我的代码我这样做:
// IN FACT, ACTUALLY "SET THE VALUES, BEFORE ANIMATING!"
theLayer.locations = newValues
// AND NOW ANIMATE:
CATransaction.begin()
...set up the animation...
CATransaction.commit()
然而,在其他的答案中的代码示例,它是这样的:
CATransaction.begin()
...set up the animation...
// IN FACT, ACTUALLY "SET THE VALUES, BEFORE ANIMATING!"
theLayer.locations = newValues
CATransaction.commit()
有关的代码行,你的位置“设置的值,动画之前!” ..
它实际上完全可以拥有该行实际上是“内部”开始提交的代码行。 只要你之前做.commit()
我只提到这一点,因为它可能会混淆新的动画制作。