Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 动画完成后,CABasicAnimation将重置为初始值_Ios_Iphone_Calayer_Cabasicanimation - Fatal编程技术网

Ios 动画完成后,CABasicAnimation将重置为初始值

Ios 动画完成后,CABasicAnimation将重置为初始值,ios,iphone,calayer,cabasicanimation,Ios,Iphone,Calayer,Cabasicanimation,我正在旋转CALayer,并试图在动画完成后将其停止在最终位置 但动画完成后,它会重置到初始位置 (xcode文档明确表示动画不会更新属性的值。) 如何实现此目标的任何建议。设置以下属性: animationObject.removedOnCompletion = NO; 这是答案,它是我的答案和克里希南的答案的结合 cabasicanimation.fillMode = kCAFillModeForwards; cabasicanimation.removedOnCompletion = N

我正在旋转CALayer,并试图在动画完成后将其停止在最终位置

但动画完成后,它会重置到初始位置

(xcode文档明确表示动画不会更新属性的值。)


如何实现此目标的任何建议。

设置以下属性:

animationObject.removedOnCompletion = NO;

这是答案,它是我的答案和克里希南的答案的结合

cabasicanimation.fillMode = kCAFillModeForwards;
cabasicanimation.removedOnCompletion = NO;

默认值为
kCAFillModeRemoved
。(这是您看到的重置行为。)

只需将其放入代码中即可

CAAnimationGroup *theGroup = [CAAnimationGroup animation];

theGroup.fillMode = kCAFillModeForwards;

theGroup.removedOnCompletion = NO;

removedOnCompletion的问题是UI元素不允许用户交互

I技术是设置动画中的“FROM”值和对象上的“to”值。 动画将在开始之前自动填充“到”值,当移除该值时,将使对象保持正确状态

// fade in
CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath: @"opacity"];
alphaAnimation.fillMode = kCAFillModeForwards;

alphaAnimation.fromValue = NUM_FLOAT(0);
self.view.layer.opacity = 1;

[self.view.layer addAnimation: alphaAnimation forKey: @"fade"];

CABasicAnimation
键添加到图层时,只需将其设置为
position
。通过这样做,它将覆盖在运行循环中当前过程位置上完成的隐式动画

CGFloat yOffset = 30;
CGPoint endPosition = CGPointMake(someLayer.position.x,someLayer.position.y + yOffset);

someLayer.position = endPosition; // Implicit animation for position

CABasicAnimation * animation =[CABasicAnimation animationWithKeyPath:@"position.y"]; 

animation.fromValue = @(someLayer.position.y);
animation.toValue = @(someLayer.position.y + yOffset);

[someLayer addAnimation:animation forKey:@"position"]; // The explicit animation 'animation' override implicit animation

您可以了解2011年苹果WWDC视频会议421的更多信息-核心动画精华(视频中间)

@Leslie Godwin的回答不是很好,“self.view.layer.opacity=1;”立即完成(大约需要一秒钟),如果您有疑问,请将alphaAnimation.duration修改为10.0。 你必须删除这条线

因此,当您将fillMode修复为kCAFillModeForwards并将removedOnCompletion修复为NO时,动画将保留在层中。如果修复动画代理并尝试以下操作:

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
 [theLayer removeAllAnimations];
}
…当您执行此行时,该层立即恢复。这是我们想要避免的

必须先修复图层特性,然后才能从中删除动画。试试这个:

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
     if([anim isKindOfClass:[CABasicAnimation class] ]) // check, because of the cast
    {
        CALayer *theLayer = 0;
        if(anim==[_b1 animationForKey:@"opacity"])
            theLayer = _b1; // I have two layers
        else
        if(anim==[_b2 animationForKey:@"opacity"])
            theLayer = _b2;

        if(theLayer)
        {
            CGFloat toValue = [((CABasicAnimation*)anim).toValue floatValue];
            [theLayer setOpacity:toValue];

            [theLayer removeAllAnimations];
        }
    }
}

CALayer有一个模型层和一个表示层。在动画期间,表示层独立于模型进行更新。动画完成后,将使用模型中的值更新表示层。如果要避免动画结束后出现抖动跳跃,关键是保持两个层同步

如果知道最终值,可以直接设置模型

self.view.layer.opacity = 1;
但是,如果您的动画不知道结束位置(例如,用户可以暂停然后反转的缓慢淡入),则可以直接查询表示层以查找当前值,然后更新模型

NSNumber *opacity = [self.layer.presentationLayer valueForKeyPath:@"opacity"];
[self.layer setValue:opacity forKeyPath:@"opacity"];
从表示层提取值对于缩放或旋转关键路径也特别有用。(例如,
transform.scale
transform.rotation

此功能:

let animation = CABasicAnimation(keyPath: "opacity")
animation.fromValue = 0
animation.toValue = 1
animation.duration = 0.3

someLayer.opacity = 1 // important, this is the state you want visible after the animation finishes.
someLayer.addAnimation(animation, forKey: "myAnimation")
核心动画在动画期间在普通层的顶部显示“表示层”。因此,将不透明度(或其他)设置为动画完成且表示层消失时希望看到的值。在添加动画之前在线上执行此操作,以避免动画完成时闪烁

如果要延迟,请执行以下操作:

let animation = CABasicAnimation(keyPath: "opacity")
animation.fromValue = 0
animation.toValue = 1
animation.duration = 0.3
animation.beginTime = someLayer.convertTime(CACurrentMediaTime(), fromLayer: nil) + 1
animation.fillMode = kCAFillModeBackwards // So the opacity is 0 while the animation waits to start.

someLayer.opacity = 1 // <- important, this is the state you want visible after the animation finishes.
someLayer.addAnimation(animation, forKey: "myAnimation")
let animation=cabasicanition(关键路径:“不透明度”)
animation.fromValue=0
animation.toValue=1
animation.duration=0.3
animation.beginTime=someLayer.convertTime(CACurrentMediaTime(),fromLayer:nil)+1
animation.fillMode=kCAFillModeBackwards//因此,当动画等待开始时,不透明度为0。

someLayer.opacity=1/简单地设置
fillMode
removedOnCompletion
对我不起作用。我通过将以下所有属性设置为Cabasicanization对象解决了问题:

CABasicAnimation* ba = [CABasicAnimation animationWithKeyPath:@"transform"];
ba.duration = 0.38f;
ba.fillMode = kCAFillModeForwards;
ba.removedOnCompletion = NO;
ba.autoreverses = NO;
ba.repeatCount = 0;
ba.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.85f, 0.85f, 1.0f)];
[myView.layer addAnimation:ba forKey:nil];

此代码将
myView
转换为其大小的85%(三维不变)。

似乎removedOnCompletion标志设置为false,fillMode设置为kCAFillModeForwards对我也不起作用

在层上应用新动画后,动画对象将重置为其初始状态,然后从该状态设置动画。 另外,在设置新动画之前,必须根据模型层的表示层属性设置模型层的所需属性,如下所示:

someLayer.path = ((CAShapeLayer *)[someLayer presentationLayer]).path;
[someLayer addAnimation:someAnimation forKey:@"someAnimation"];

不使用
removedOnCompletion

您可以尝试以下技巧:

self.animateOnX(item: shapeLayer)

func animateOnX(item:CAShapeLayer)
{
    let endPostion = CGPoint(x: 200, y: 0)
    let pathAnimation = CABasicAnimation(keyPath: "position")
    //
    pathAnimation.duration = 20
    pathAnimation.fromValue = CGPoint(x: 0, y: 0)//comment this line and notice the difference
    pathAnimation.toValue =  endPostion
    pathAnimation.fillMode = kCAFillModeBoth

    item.position = endPostion//prevent the CABasicAnimation from resetting item's position when the animation finishes

    item.add(pathAnimation, forKey: nil)
}

所以我的问题是,我试图在平移手势上旋转一个对象,所以我在每个动作上都有多个相同的动画。我有两个
fillMode=kCAFillModeForwards
isRemovedOnCompletion=false
,但都没有帮助。在我的例子中,每次添加新动画时,我必须确保动画关键点不同:

let angle = // here is my computed angle
let rotate = CABasicAnimation(keyPath: "transform.rotation.z")
rotate.toValue = angle
rotate.duration = 0.1
rotate.isRemovedOnCompletion = false
rotate.fillMode = CAMediaTimingFillMode.forwards

head.layer.add(rotate, forKey: "rotate\(angle)")

核心动画维护两个层层次:和。动画进行时,模型层实际上是完整的,并保持其初始值。默认情况下,动画完成后将被删除。然后表示层返回到模型层的值

只需将
removedOnCompletion
设置为
NO
就意味着动画不会被删除,并且会浪费内存。此外,模型层和表示层将不再同步,这可能会导致潜在的错误

因此,将模型层上的特性直接更新为最终值是更好的解决方案

self.view.layer.opacity = 1;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue = 0;
animation.toValue = 1;
[self.view.layer addAnimation:animation forKey:nil];
如果有任何由上述代码的第一行引起的隐式动画,请尝试禁用:

[CATransaction begin];
[CATransaction setDisableActions:YES];
self.view.layer.opacity = 1;
[CATransaction commit];

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue = 0;
animation.toValue = 1;
[self.view.layer addAnimation:animation forKey:nil];
  • 参考:
    • 由objc.io编写
    • 罗伯·纳皮尔和穆贡·库马尔

    • 最简单的解决方案是使用隐式动画。这将为您解决所有这些问题:

      self.layer?.backgroundColor = NSColor.red.cgColor;
      
      如果要自定义例如持续时间,可以使用
      NSAnimationContext

          NSAnimationContext.beginGrouping();
          NSAnimationContext.current.duration = 0.5;
          self.layer?.backgroundColor = NSColor.red.cgColor;
          NSAnimationContext.endGrouping();
      
      注意:这仅在macOS上测试

      当我这样做的时候,我最初没有看到任何动画。问题在于,视图支持层的层不执行隐式动画。要解决此问题,请确保您自己添加了一个层(在设置v之前)
      override func awakeFromNib() {
          self.layer = CALayer();
          //self.wantsLayer = true;
      }
      
      import PlaygroundSupport
      import UIKit
      
      let resultRotation = CGFloat.pi / 2
      let view = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 200.0, height: 300.0))
      view.backgroundColor = .red
      
      //--------------------------------------------------------------------------------
      
      let rotate = CABasicAnimation(keyPath: "transform.rotation.z") // 1
      rotate.fromValue = CGFloat.pi / 3 // 2
      rotate.toValue = resultRotation // 3
      rotate.duration = 5.0 // 4
      rotate.beginTime = CACurrentMediaTime() + 1.0 // 5
      // rotate.isRemovedOnCompletion = false // 6
      rotate.fillMode = .backwards // 7
      
      view.layer.add(rotate, forKey: nil) // 8
      view.layer.setAffineTransform(CGAffineTransform(rotationAngle: resultRotation)) // 9
      
      //--------------------------------------------------------------------------------
      
      PlaygroundPage.current.liveView = view