(iOS)如何使用shapeLayer为圆角矩形设置动画?

时间:2012-06-19 10:42:58

标签: ios animation core-animation shape cashapelayer

我试图为圆角矩形的宽度设置动画,问题是当从更大的宽度变为更宽的宽度时,动画会进行“像差轻松跳跃”。

以下是代码:

shapeLayer = [CAShapeLayer layer];
shapeRect = CGRectMake(0.0f, 0.0f, 150.0f, 200.0f);
[shapeLayer setBounds:shapeRect];
[shapeLayer setPosition:CGPointMake(iniPosX, 80.0f)];
[shapeLayer setFillColor:[[UIColor blackColor] CGColor]];
[shapeLayer setStrokeColor:[[UIColor clearColor] CGColor]];
[shapeLayer setLineWidth:1.0f];
[shapeLayer setLineJoin:kCALineJoinRound];
[shapeLayer setOpacity:0.2];
path = [UIBezierPath bezierPathWithRoundedRect:shapeRect cornerRadius:15.0];
[shapeLayer setPath:path.CGPath];
[self.layer addSublayer:shapeLayer];

当我开始动画时:

- (void)adjustSelectorToPosAndSize:(float)posX andWidth:(float)width
{
    shapeRect = CGRectMake(0.0f, 0.0f, width, 200.0f);
    [shapeLayer setBounds:shapeRect];
    [shapeLayer setPosition:CGPointMake(posX, 80.0f)];
    path = [UIBezierPath bezierPathWithRoundedRect:shapeRect cornerRadius:15.0];
    [shapeLayer setPath:path.CGPath];
}

我做错了什么?

2 个答案:

答案 0 :(得分:3)

虽然CAShapeLayer的path属性是可动画的,但它不会像边界和位置那样隐式地执行,你必须制作一个显式的动画:

CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath: @"path"];
anim.fromValue = (id) fromPath.CGPath;
anim.toValue = (id) toPath.CGPath;
anim.duration = 1.0;
[layer addAnimation: anim forKey: @“resize”];

由于您可能希望所有三个动画一起发生,因此您可以将它们全部显示并组合在一起:

CABasicAnimation* anim1 = [CABasicAnimation animationWithKeyPath: @"position"];
anim1.fromValue = [NSValue valueWithCGPoint: fromPosition];
anim1.toValue = [NSValue valueWithCGPoint: toPosition];
anim1.duration = 1.0;

CABasicAnimation* anim2 = [CABasicAnimation animationWithKeyPath: @"bounds"];
anim2.fromValue = [NSValue valueWithCGRect: fromBounds];
anim2.toValue = [NSValue valueWithCGRect: toBounds];
anim2.duration = 1.0;

CABasicAnimation* anim3 = [CABasicAnimation animationWithKeyPath: @"path"];
anim3.fromValue = (id) fromPath.CGPath;
anim3.toValue = (id) toPath.CGPath;
anim3.duration = 1.0;

CAAnimationGroup* animG = [CAAnimationGroup animation];
animG.animations = [NSArray arrayWithObjects: anim1, anim2, anim3, nil];
animG.duration = 1.0;
[layer addAnimation: animG forKey:@"resize"];

如果您的形状没有内容或儿童,那么您可以改为使用CALayer:

CALayer* rectLayer = [CALayer layer];
rectLayer.masksToBounds = YES;
rectLayer.bounds = startBounds;
rectLayer.backgroundColor = [[UIColor blackColor] CGColor];
rectLayer.cornerRadius = 15.0;
[self.layer addSublayer: rectLayer];

// Then later implicitly animate the bounds:
rectLayer.bounds = newBounds;

答案 1 :(得分:3)

使用CAShapeLayer执行此操作对我来说似乎过于复杂,如果您只将它用于圆角矩形。为什么不简单地使用the cornerRadius properly设置的CALayer?

使用cornerRadius设置动画帧将正常工作。

myLayer = [CALayer layer];
shapeRect = CGRectMake(0.0f, 0.0f, 150.0f, 200.0f);
[myLayer setBounds:shapeRect];
[myLayer setPosition:CGPointMake(iniPosX, 80.0f)];
[myLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
[myLayer setBorderColor:[[UIColor clearColor] CGColor]];
[myLayer setBorderWidth:1.0f];
[myLayer setOpacity:0.2];
[myLayer setCornerRadius:15.0];
[self.layer addSublayer:myLayer];

通过简单地链接框架(而不是路径)来完成动画

- (void)adjustSelectorToPosAndSize:(float)posX andWidth:(float)width
{
    shapeRect = CGRectMake(0.0f, 0.0f, width, 200.0f);
    [myLayer setBounds:shapeRect];
    [myLayer setPosition:CGPointMake(posX, 80.0f)];
}

重要:

某些属性更改名称fillColor变为backgroundColorstrokeColorlineWidth变为borderColorborderWidth等。