Ios 如何旋转包含UIBezierPath的CAShapeLayer?

Ios 如何旋转包含UIBezierPath的CAShapeLayer?,ios,rotation,calayer,Ios,Rotation,Calayer,可能重复: 我搜索和测试了几个小时的各种代码,但我无法让它工作 我将在随机位置向CAShapeLayer添加任意UIBezierPath,该CAShapeLayer将添加到视图中。我需要旋转路径,以便处理设备旋转。我可以旋转图层而不是路径。我只需要旋转结果 我已经有了通过缩放和平移来处理贝塞尔路径变换的方法。它工作得很好,但现在我需要简单地向左或向右旋转90度 有没有关于如何做到这一点的建议 基本代码: UIBezierPath *path = <create arbitrary pat

可能重复:

我搜索和测试了几个小时的各种代码,但我无法让它工作

我将在随机位置向CAShapeLayer添加任意UIBezierPath,该CAShapeLayer将添加到视图中。我需要旋转路径,以便处理设备旋转。我可以旋转图层而不是路径。我只需要旋转结果

我已经有了通过缩放和平移来处理贝塞尔路径变换的方法。它工作得很好,但现在我需要简单地向左或向右旋转90度

有没有关于如何做到这一点的建议

基本代码:

UIBezierPath *path = <create arbitrary path>
CAShapeLayer *layer = [CAShapeLayer layer];
[self addPathToLayer:layer
             fromPath:path];

// I could get the center of the box but where is the box center for the view it is in?
// CGRect box = CGPathGetPathBoundingBox(path.CGPath);

// layer.anchorPoint = ? How to find the center of the box for the anchor point?

// Rotating here appears to rotate around 0,0 of the view
layer.transform = CATransform3DMakeRotation(DegreesToRadians(-90), 0.0, 0.0, 1.0);
此值是启动/停止应用程序并进行调整时的猜测值。我不知道为什么我需要调整旋转时的位置。锚定点应位于层的中心。但是,我确实发现,即使设置了路径,CAShapeLayer的帧和位置都为零,而且路径在视图中处于正确的位置。旋转+90时,280,60位置将路径移动到路径边界框的中心。如果更改旋转值,则需要调整位置。我不必手动进行此调整

我认为最后的办法是以某种方式将贝塞尔路径转换为图像,然后添加它。我发现,如果我将图层内容设置为图像,然后旋转,它将围绕其中心点旋转,而无需进行位置调整。设置路径时情况并非如此

更新#2 2012年12月4日-我尝试设置框架,并通过摆弄将其置于中心,如下所示:

CGRect box = CGPathGetPathBoundingBox(path.CGPath);
CGRect rect = CGRectMake(0, 0, box.origin.x + (3.5 * box.size.width), box.origin.y + (3.5 * box.size.height));
layer.frame = rect;
layer.transform = CATransform3DMakeRotation(DegreesToRadians(90), 0.0, 0.0, 1.0);
为什么要乘以3.5?我不知道。我发现添加大小约为长方体3.5倍的长方体原点会将旋转的CAShapeLayer路径移动到它应该位于的位置

必须有更好的方法来做到这一点。这是一个比我上一篇文章更好的解决方案,因为帧大小不依赖于旋转角度。我只是不知道为什么帧需要设置为我要设置的值。我想应该是的 CGRectMake(0,0,box.origin.x+(box.size.width/2),box.origin.y+(box.size.height/2))

但是,它将图像向左移动太多

我发现的另一个线索是,如果我设置[self view].frame(整个父视图的框架,即iPhone的屏幕)的框架,然后旋转,旋转点是屏幕的中心,路径/图像围绕该中心旋转。这就是为什么我尝试将帧移动到路径的中心,使其围绕长方体中心旋转

更新#3 2012年12月4日-我尝试将图层渲染为图像。但是,仅设置层的路径似乎不会使其成为层中的“图像”,因为它是空的

    CGRect box = CGPathGetPathBoundingBox(path.CGPath);
    layer.frame = box;

    UIImage *image = [ImageHelper imageFromLayer:layer]; // ImageHelper library I created  

    CAShapeLayer *newLayer = [CAShapeLayer layer];
    newLayer.frame = CGRectMake(box.origin.x, box.origin.y, image.size.width, image.size.height);
    newLayer.contents = (id) image.CGImage;
看起来,使用路径集旋转图层与简单地旋转贝塞尔路径本身没有什么不同。我将返回到旋转贝塞尔路径,看看我是否可以摆弄位置元素或其他东西。一定有办法解决这个问题

目标:在最初创建UIBezierPath的视图中围绕其中心点旋转UIBezierPath

更新#4 2012年12月4日-我运行了一系列测试,测量转换所需的值,以便将UIBezierPath放置在其先前的中心位置

CGAffineTransform rotate = CGAffineTransformMakeRotation(DegreesToRadians(-15));
[path applyTransform:rotate];

// CGAffineTransform translate = CGAffineTransformMakeTranslation(-110, 70); // -45
CGAffineTransform translate = CGAffineTransformMakeTranslation(-52, -58); // -15
[path applyTransform:translate];
但是,x/y平移的比率并不对应,因此我无法根据角度推断需要进行哪些平移。“CGAffineTransformMakeRotation”似乎使用了一些任意定位点来进行旋转,目前看起来可能是(viewWidth/2,0)。我让这件事变得比需要的困难得多。我缺少一些东西来进行简单的旋转,以便保持中心点。我只需要将路径向左或向右旋转90度


更新#5 2012年12月4日-运行其他测试后,旋转UIBezierPath的定位点似乎是绘制所有点的原点。在这种情况下,原点为0,0,并且所有点都相对于该点。因此,如果应用了旋转,旋转将围绕原点发生,这就是为什么路径在-90上向右移动,在90上向左移动。我需要以某种方式将旋转的锚点设置为中心,使其围绕中心“旋转”,而不是原始原点。在这一问题上花了12个小时。

经过一些详细的分析并在纸上画出边界框后,我发现我的断言0,0的起源是正确的

此问题的解决方案是将路径(基础矩阵)平移到原点,使边界框的中心位于原点,旋转,然后将路径平移回其原始位置

CGAffineTransform rotate = CGAffineTransformMakeRotation(DegreesToRadians(-15));
[path applyTransform:rotate];

// CGAffineTransform translate = CGAffineTransformMakeTranslation(-110, 70); // -45
CGAffineTransform translate = CGAffineTransformMakeTranslation(-52, -58); // -15
[path applyTransform:translate];
以下是如何将UIBezierPath旋转90度:

CGAffineTransform translate = CGAffineTransformMakeTranslation(-1 * (box.origin.x + (box.size.width / 2)), -1 * (box.origin.y + (box.size.height / 2)));
[path applyTransform:translate];

CGAffineTransform rotate = CGAffineTransformMakeRotation(DegreesToRadians(90));
[path applyTransform:rotate];

translate = CGAffineTransformMakeTranslation((box.origin.x + (box.size.width / 2)), (box.origin.y + (box.size.height / 2)));
[path applyTransform:translate];
插入-90度,以向另一个方向旋转

将设备从纵向旋转到横向时,可以使用此公式,反之亦然

我仍然不认为这是理想的解决方案,但结果是我现在需要的

如果有人对此有更好的解决方案,请张贴

更新2012年12月7日-我发现我认为是最好的解决方案,而且非常简单,尽管我认为这将是。我没有在bezier路径上使用旋转、平移和缩放方法,而是将点阵列提取为CGPoint对象,并根据视图大小和方向根据需要缩放/平移它们。然后我创建一个新的贝塞尔路径,并将图层设置为该路径


结果是完美的缩放、平移和旋转。

我希望我能看到你是如何做到你在更新中所说的@christopher@Reza.Ab仅当设备方向更改且视图大小调整后,即可根据根据新视图大小计算的新点的位置重新绘制贝塞尔路径