5

我正在尝试为圆角矩形的宽度设置动画,问题是当从更大的宽度变为更薄的宽度时,动画会出现“像差缓和跳跃”。

这是代码:

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

我究竟做错了什么?

4

2 回答 2

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;
于 2012-06-22T20:19:22.897 回答
3

如果您仅将它用于圆角矩形,那么使用 CAShapeLayer 执行此操作对我来说似乎过于复杂。为什么不简单地使用正确设置cornerRadiusCALayer ?

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

重要的:

一些属性更改了名称,例如fillColorbecomebackgroundColor和 the strokeColorand lineWidthbecomeborderColorborderWidth

于 2012-06-22T20:47:53.230 回答