首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >旋转CGPath而不更改其位置

旋转CGPath而不更改其位置
EN

Stack Overflow用户
提问于 2012-12-06 14:48:57
回答 4查看 14K关注 0票数 12

我想旋转一个CGPath,我使用了下面的代码:

代码语言:javascript
运行
复制
CGAffineTransform transform = CGAffineTransformMakeRotation(angleInRadians);
CGPathRef rotatedPath = CGPathCreateCopyByTransformingPath(myPath, &transform);

这段代码运行得很好,但是它改变了path的位置!我希望路径保持在旋转前的相同位置。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-12-06 15:08:47

路径没有“位置”。路径是一组点(由直线段和曲线段定义)。每个点都有自己的位置。

您可能希望围绕特定点旋转路径,而不是绕原点旋转。诀窍是创建一个组合了三个独立变换的复合变换:

从步骤1开始,

  1. 将原点转换为旋转并进行平移。

例如,下面的函数接受一个路径并返回一个新路径,该路径是围绕其边界框中心旋转的原始路径:

代码语言:javascript
运行
复制
static CGPathRef createPathRotatedAroundBoundingBoxCenter(CGPathRef path, CGFloat radians) {
    CGRect bounds = CGPathGetBoundingBox(path); // might want to use CGPathGetPathBoundingBox
    CGPoint center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
    CGAffineTransform transform = CGAffineTransformIdentity;
    transform = CGAffineTransformTranslate(transform, center.x, center.y);
    transform = CGAffineTransformRotate(transform, radians);
    transform = CGAffineTransformTranslate(transform, -center.x, -center.y);
    return CGPathCreateCopyByTransformingPath(path, &transform);
}

请注意,此函数返回一个具有+1保留计数的新路径,您负责在使用完成后将其释放。例如,如果您尝试旋转形状图层的路径:

代码语言:javascript
运行
复制
- (IBAction)rotateButtonWasTapped:(id)sender {
    CGPathRef path = createPathRotatedAroundBoundingBoxCenter(shapeLayer_.path, M_PI / 8);
    shapeLayer_.path  = path;
    CGPathRelease(path);
}

更新

这是一个使用Swift游乐场的演示。我们将从一个辅助函数开始,该函数显示路径并用十字光标标记原点:

代码语言:javascript
运行
复制
import UIKit
import XCPlayground

func showPath(label: String, path: UIBezierPath) {
    let graph = UIBezierPath()
    let r = 40
    graph.moveToPoint(CGPoint(x:0,y:r))
    graph.addLineToPoint(CGPoint(x:0,y:-r))
    graph.moveToPoint(CGPoint(x:-r,y:0))
    graph.addLineToPoint(CGPoint(x:r,y:0))
    graph.appendPath(path)
    XCPCaptureValue(label, graph)
}

接下来,下面是我们的测试路径:

代码语言:javascript
运行
复制
var path = UIBezierPath()
path.moveToPoint(CGPoint(x:1000,y:1000))
path.addLineToPoint(CGPoint(x:1000,y:1200))
path.addLineToPoint(CGPoint(x:1100,y:1200))
showPath("original", path)

(请记住,十字准线是原点,不是我们要转换的路径的一部分。)

我们得到中心并变换路径,使其以原点为中心:

代码语言:javascript
运行
复制
let bounds = CGPathGetBoundingBox(path.CGPath)
let center = CGPoint(x:CGRectGetMidX(bounds), y:CGRectGetMidY(bounds))

let toOrigin = CGAffineTransformMakeTranslation(-center.x, -center.y)
path.applyTransform(toOrigin)
showPath("translated center to origin", path)

然后我们旋转它。所有旋转都发生在原点周围:

代码语言:javascript
运行
复制
let rotation = CGAffineTransformMakeRotation(CGFloat(M_PI / 3.0))
path.applyTransform(rotation)
showPath("rotated", path)

最后,我们将其翻译回来,准确地颠倒原始翻译:

代码语言:javascript
运行
复制
let fromOrigin = CGAffineTransformMakeTranslation(center.x, center.y)
path.applyTransform(fromOrigin)
showPath("translated back to original center", path)

请注意,我们必须对原始转换进行反转。我们不通过它的新边界框的中心进行平移。回想一下(在本例中),原始中心位于(1050,1100)。但是在我们将它平移到原点并旋转之后,新边界框的中心是(-25,0)。将路径平移(-25,0)将不会使其接近原始位置!

票数 62
EN

Stack Overflow用户

发布于 2019-11-12 01:56:45

Swift 5版本:

代码语言:javascript
运行
复制
func rotate(path: UIBezierPath, degree: CGFloat) {
    let bounds: CGRect = path.cgPath.boundingBox
    let center = CGPoint(x: bounds.midX, y: bounds.midY)

    let radians = degree / 180.0 * .pi
    var transform: CGAffineTransform = .identity
    transform = transform.translatedBy(x: center.x, y: center.y)
    transform = transform.rotated(by: radians)
    transform = transform.translatedBy(x: -center.x, y: -center.y)
    path.apply(transform)
}
票数 7
EN

Stack Overflow用户

发布于 2017-02-03 06:27:04

围绕矩形中心就地旋转矩形的Swift 3方法:

代码语言:javascript
运行
复制
func createRotatedCGRect(rect: CGRect, radians: CGFloat) -> CGPath {
    let center = CGPoint(x: rect.midX, y: rect.midY)
    let path = UIBezierPath(rect: rect)
    path.apply(CGAffineTransform(translationX: center.x, y: center.y).inverted())
    path.apply(CGAffineTransform(rotationAngle: radians))
    path.apply(CGAffineTransform(translationX: center.x, y: center.y))
    return path.cgPath
}

rob mayoff将其应用于路径及其边界框的所有代码仍然适用,所以我没有看到重复它们的原因。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13738364

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档