Objective-C的 - CABasicAnimation动画完成后,将改变?(Objecti

2019-06-17 11:26发布

我使用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];

Answer 1:

当您添加一个动画层,动画不改变层的性能。 相反,系统会创建层的副本。 原来层称为模型层,并重复被称为表现层。 表示层的属性改变作为动画的进展,但该模型层的性质保持不变。

当您删除的动画,系统破坏了表示层,只留下模型层,然后在模型层的特性控制层的绘制。 所以,如果模型层的特性不匹配的表现层的属性的最终动画值,该层将立即恢复到动画之前它的外观。

为了解决这个问题,你需要设置模型层的属性,以动画的最终值, 然后将动画添加到该层。 你想这样做的顺序,因为改变图层属性可以为属性,它会跟你要明确添加动画冲突添加一个隐含的动画。 你要确保你的动画明确覆盖隐式动画。

那么,你如何做到这一切的? 基本配方如下:

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];


Answer 2:

CAAnimations自动完成时删除。 有一个属性removedOnCompletion控制这一点。 你应该设置到NO

此外,有一些被称为fillMode这之前,其持续时间后,控制动画的行为。 这是声明的属性CAMediaTiming (其中CAAnimation符合)。 你应该将其设置为kCAFillModeForwards

与这两个变化的动画应该坚持它完成之后。 不过,我不知道你是否需要更改这些对本集团或对本集团,或两者中的各个动画。



Answer 3:

继承人在斯威夫特的例子,可以帮助别人

这是一个梯度层上的动画。 它的动画的.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()

我只提到这一点,因为它可能会混淆新的动画制作。



文章来源: Objective-C - CABasicAnimation applying changes after animation?