-->

动画CAShapeLayer尺寸变化(Animating CAShapeLayer size cha

2019-07-03 19:38发布

我画一个圆圈,用200的初始半径

self.circle = [CAShapeLayer layer];
self.circle.fillColor = nil;
self.circle.strokeColor = [UIColor blackColor].CGColor;
self.circle.lineWidth = 7;
self.circle.bounds = CGRectMake(0, 0, 2 * radius, 2 * radius);
self.circle.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.radius, self.radius)

谁能告诉我如何制作动画的变化,以100为半径?

Answer 1:

这是我最后只是:

UIBezierPath *newPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(newRadius, newRadius) radius:newRadius startAngle:(-M_PI/2) endAngle:(3*M_PI/2) clockwise:YES];
CGRect newBounds = CGRectMake(0, 0, 2 * newRadius, 2 * newRadius);

CABasicAnimation* pathAnim = [CABasicAnimation animationWithKeyPath: @"path"];
pathAnim.toValue = (id)newPath.CGPath;

CABasicAnimation* boundsAnim = [CABasicAnimation animationWithKeyPath: @"bounds"];
boundsAnim.toValue = [NSValue valueWithCGRect:newBounds];

CAAnimationGroup *anims = [CAAnimationGroup animation];
anims.animations = [NSArray arrayWithObjects:pathAnim, boundsAnim, nil];
anims.removedOnCompletion = NO;
anims.duration = 2.0f;
anims.fillMode  = kCAFillModeForwards;

[self.circle addAnimation:anims forKey:nil];

由于雅各布指着我在正确的方向。



Answer 2:

这一点,我相信,简单的和最佳的方式做到这一点:

UIBezierPath *newPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(newRadius, newRadius) radius:newRadius startAngle:(-M_PI/2) endAngle:(3*M_PI/2) clockwise:YES];
CABasicAnimation* pathAnim = [CABasicAnimation animationWithKeyPath:@"path"];
pathAnim.fromValue = (id)self.circle.path;
pathAnim.toValue = (id)newPath.CGPath;
pathAnim.duration = 2.0f;
[self.circle addAnimation:pathAnim forKey:@"animateRadius"];

self.circle.path = newPath.CGPath;

我从这个方法苹果文档这里 (参见清单3-2)。 这里最重要的事情是,你设置fromValue并设置终值self.circlepathnewPath.CGPath右侧设置了动画后。 动画不会改变模型的潜在价值,所以在另一种方法,你没有真正做的形状层的永久改变path变量。

我使用(使用像过去所选择的答案的解决方案removedOnCompletionfillMode等),但我发现,iOS上的某些版本中他们造成内存泄露,也有时这种做法只是没有出于某种原因。

通过这种方法,你明确地创建动画(包括它的开始,在哪里结束), 并且你在最后指定的路径最终永久值(与上线),以便有没有必要与不删除当它完成动画一塌糊涂(我相信是如果你这样做动画了很多次什么导致内存泄漏...未去除的动画建立在内存中)。

另外,我删除了动画bounds ,因为你不需要它动画圆。 即使路径绘制层的边界之外,它仍然尽显(请参阅文档CAShapeLayer有关)。 如果你确实需要动画一些其他原因的界限,你可以使用相同的方法(确保指定fromValue和边界的最终值)。



Answer 3:

您可以使用CAAnimationGroup动画的boundspath您的CAShapeLayer

- (void)animateToRadius:(CGFloat)newRadius {
   CAShapeLayer *shapeLayer = ...;

   UIBezierPath *newBezierPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(newRadius, newRadius)];
   NSValue *newBounds = [NSValue valueWithCGRect:CGRectMake(0,0,2*newRadius,2*newRadius);

   CAAnimationGroup *group = [CAAnimationGroup animation];

   NSMutableArray *animations  = [@[] mutableCopy];
   NSDictionary *animationData = @{@"path":newBezierPath.CGPath, @"bounds":newBounds};
   for(NSString *keyPath in animationData) {
      CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:keyPath];
      animation.toValue   = animationData[keyPath];
      [animations addObject:animation];
   }

   group.animations = [animations copy];
   group.duration = 2;
   group.removedOnCompletion = NO;
   group.fillMode = kCAFillModeForwards;

   [shapeLayer addAnimation:group forKey:nil];
}


Answer 4:

下面是乔纳森的代码直接转换迅速如若有人需要它。

func scaleShape(shape : CAShapeLayer){

    let newRadius : CGFloat = 50;

    let newPath: UIBezierPath = UIBezierPath(arcCenter: CGPointMake(newRadius, newRadius), radius: newRadius, startAngle: (CGFloat(-M_PI) / 2.0), endAngle: (3 * CGFloat(M_PI) / 2), clockwise: true);


    let newBounds : CGRect = CGRect(x: 0, y: 0, width: 2 * newRadius, height: 2 * newRadius);
    let pathAnim : CABasicAnimation = CABasicAnimation(keyPath: "path");

    pathAnim.toValue = newPath.CGPath;

    let boundsAnim : CABasicAnimation = CABasicAnimation(keyPath: "bounds");
    boundsAnim.toValue = NSValue(CGRect: newBounds);

    let anims: CAAnimationGroup = CAAnimationGroup();
    anims.animations = [pathAnim, boundsAnim];
    anims.removedOnCompletion = false;
    anims.duration = 2.0;
    anims.fillMode = kCAFillModeForwards;

    shape.addAnimation(anims, forKey: nil);
}


文章来源: Animating CAShapeLayer size change