旋转 CAShapeLayer 也会移动位置

Rotating CAShapeLayer moves the position too

我正在创建一个 CAShapeLayer。我正在为其添加旋转动画。不知何故,转换结果很奇怪。子层随着旋转而移动。我需要它固定 center/position(anchor) 并旋转。我知道它搞乱了几何变换,但我无法正确处理。

我试过设置锚点。我也关注了这个 post

代码如下:

UIBezierPath *circle = [UIBezierPath bezierPathWithArcCenter:CGPointMake(75, 125)
                                                      radius:50
                                                  startAngle:0
                                                    endAngle:1.8 * M_PI
                                                   clockwise:YES];

CAShapeLayer *circleLayer = [CAShapeLayer layer];
[circleLayer setFrame:CGRectMake(200 - 50, 300 - 50, 100, 100)];
circleLayer.path   = circle.CGPath;
circleLayer.strokeColor = [UIColor orangeColor].CGColor;
[circleLayer setFillColor:[UIColor clearColor].CGColor];
circleLayer.lineWidth   = 3.0;

if ([circleLayer animationForKey:@"SpinAnimation"] == nil) {
    CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    animation.fromValue = [NSNumber numberWithFloat:0.0f];
    animation.toValue = [NSNumber numberWithFloat: 2 * M_PI];
    animation.duration = 10.0f;
    animation.repeatCount = INFINITY;
    animation.removedOnCompletion = NO;
    [circleLayer addAnimation:animation forKey:@"SpinAnimation"];
}

[self.view.layer addSublayer:circleLayer];

它工作正常。只需为您的图层启用框架:

circleLayer.borderWidth = 1;
circleLayer.borderColor = [UIColor redColor].CGColor;

你看到那个框架向右旋转。也最好在这里使用 byValue

CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
animation.byValue = @(2 * M_PI);
animation.duration = 10.0f;
animation.repeatCount = INFINITY;
animation.removedOnCompletion = NO;
[circleLayer addAnimation:animation forKey:@"SpinAnimation"];

所以你的问题是几何形状。

tl;dr: 您的形状图层缺少一个框架(可能是其路径的边界框)。


令人困惑的是被旋转的图层没有框架。这意味着它的大小是0⨉0。这与形状层允许在其边界之外绘制形状这一事实相结合,使得旋转看起来像是围绕外部点发生的。但事实并非如此。

问题

在不对锚点进行任何修改的情况下,变换是相对于图层自身边界的中心发生的。对于没有大小的层,中心与原点相同(当widthheight都为0时,(x+width/2, y+height/2)(x, y)相同) .

本地原点(相对于图层的边界)也是绘制路径的相对位置。路径的点 (0, 0) 位于形状图层的原点。

如果我们要显示图层的中心(在本例中为原点),这就是它的样子。

这也是形状旋转的点。

正在解决...

基本上有两种解决这个问题的方法,使它围绕圆心旋转。一种是改变路径,使圆心位于原点 (0,0)。我通常更喜欢的另一种解决方案是为图层提供与其路径大小相匹配的大小,即路径边界框:

circleLayer.bounds = CGPathGetBoundingBox(circle.CGPath);

这里我显示的图层具有非常浅的灰色背景颜色:

我有时发现在作为调试工具的开发过程中为形状图层提供背景颜色很有用,这样我就可以看到它的框架符合我的预期。

请注意,当您更改图层或视图的边界时,它会根据其位置调整大小。这意味着中心点保持不变,原点移动,意味着路径将有效移动。

既然图层有一个大小,并且边界的中心与圆的中心相匹配,那么当您旋转形状图层时,圆看起来就像围绕它的中心旋转。

当您看到一切正常时,您可以再次删除背景颜色。