Asi*_*eba 10 iphone core-graphics objective-c ios
我想旋转一个CGPath,我使用以下代码:
CGAffineTransform transform = CGAffineTransformMakeRotation(angleInRadians);
CGPathRef rotatedPath = CGPathCreateCopyByTransformingPath(myPath, &transform);
这段代码工作正常,但它改变了路径的位置!我希望路径保持与旋转前相同的位置.
rob*_*off 60
路径没有"位置".路径是一组点(由线段和曲线段定义).每一点都有自己的立场.
也许您想要围绕特定点旋转路径,而不是围绕原点旋转.诀窍是创建一个组合三个变换的复合变换:
例如,这是一个获取路径并返回一条新路径的函数,该路径是围绕其边界框旋转的原始路径:
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保留计数,当您完成该计数时,您将负责释放该计数.例如,如果您尝试旋转形状图层的路径:
- (IBAction)rotateButtonWasTapped:(id)sender {
    CGPathRef path = createPathRotatedAroundBoundingBoxCenter(shapeLayer_.path, M_PI / 8);
    shapeLayer_.path  = path;
    CGPathRelease(path);
}
这是使用Swift游乐场的演示.我们将从一个显示路径的辅助函数开始,并用十字准线标记原点:
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)
}
接下来,这是我们的测试路径:
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)

(请记住,十字准线是原点,不是我们正在改造的路径的一部分.)
我们获得中心并转换路径,使其以原点为中心:
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)

然后我们旋转它.所有旋转都发生在原点周围:
let rotation = CGAffineTransformMakeRotation(CGFloat(M_PI / 3.0))
path.applyTransform(rotation)
showPath("rotated", path)

最后,我们将其翻译回来,完全颠倒原始翻译:
let fromOrigin = CGAffineTransformMakeTranslation(center.x, center.y)
path.applyTransform(fromOrigin)
showPath("translated back to original center", path)

请注意,我们必须反转原始翻译.我们不会通过其新边界框的中心进行翻译.回想一下(在这个例子中),原始中心位于(1050,1100).但是在我们将其转换为原点并旋转它之后,新的边界框的中心位于(-25,0).将路径翻译为(-25,0)不会使其接近原始位置!
Swift 5 版本:
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)
}
| 归档时间: | 
 | 
| 查看次数: | 12003 次 | 
| 最近记录: |