我正在绘制一个圆,初始半径为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的动画吗?
答案 0 :(得分:23)
这就是我最终做到的方式:
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];
感谢雅各布指出我正确的方向。
答案 1 :(得分:11)
我认为,这是一种更简单,更首选的方式:
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;
我从Apple Documentation here得到了这种方法(参见清单3-2)。这里重要的是您设置fromValue
并在设置动画后立即将self.circle
的{{1}}的最终值设置为path
。动画不会更改模型的基础值,因此在另一种方法中,您实际上并未对形状图层的newPath.CGPath
变量进行永久性更改。
我过去使用了一个类似于所选答案的解决方案(使用path
和removedOnCompletion
等),但我发现在某些版本的iOS上它们会导致内存泄漏,有时也会出现这种情况因某种原因无法正常工作。
使用这种方法,您可以显式创建动画(无论是从哪里开始,也可以在结束的位置),和您在末尾指定路径的最终永久值(使用那个最后一行),所以没有必要在完成时不要删除动画(我相信如果你很多时候这个动画会导致内存泄漏......那些未被删除的动画会在内存中建立)
此外,我删除了fillMode
的动画,因为您不需要它来为圆圈设置动画。即使路径被绘制到图层的边界之外,它仍然会完全显示(请参阅bounds
的文档)。如果您确实需要为某些其他原因设置边界的动画,可以使用相同的方法(确保指定CAShapeLayer
和边界的最终值)。
答案 2 :(得分:2)
您可以使用CAAnimationGroup
为bounds
的{{1}}和path
制作动画:
CAShapeLayer
答案 3 :(得分:2)
如果有人需要,可以直接快速转换Jonathan的代码。
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);
}