UIBezierPath转换转换给出了错误的答案

时间:2017-06-05 10:11:07

标签: ios swift uibezierpath cgpath

当我尝试翻译路径时,要将其移动到{0,0}的原点,结果路径边界是错误的。 (或者,我的假设是错误的)。

e.g。路径提供以下边界信息:

let bezier = UIBezierPath(cgPath: svgPath)
print(bezier.bounds)

// (0.0085, 0.7200, 68.5542, 41.1379)

print(bezier.cgPath.boundingBoxOfPath)

// (0.0085, 0.7200, 68.5542, 41.1379)

print(bezier.cgPath.boundingBox)

// (-1.25, -0.1070, 70.0360, 41.9650)

我(尝试)将路径移动到原点:

let origin = bezier.bounds.origin
bezier.apply(CGAffineTransform(translationX: -origin.x, y: -origin.y))

print(bezier.bounds)

// (0.0, -2.7755, 68.5542, 41.1379)

正如您所看到的,x origin组件在0处是正确的。但是,y component( - 2.755)已经全部变成了kittywumpus。它应该是0,非?

当我在cgPath属性上执行转换时,会发生同样的事情。

是否有人知道在翻译时UIBezierPath/CGPath会出现什么样的情况?阅读Apple文档后,似乎UIBezierPath/CGPath没有变换状态;在调用变换时立即转换点。

感谢您的帮助。

背景:

路径数据来自Font-Awesome SVG,来自PocketSVG。所有文件都解析,大多数绘制正常。但是一小部分表现出上述翻译问题。在我浏览SVG解析,寻找缺陷的路径构建代码之前,我想知道我是否做了一些根本错误或愚蠢的事情。

顺便说一句,我不是在这个阶段画画,也不是在处理一个背景;我正在绘制之前构建路径。

[编辑]

为了检查PocketSVG是否给我正确形成的数据,我将相同的SVG传递给SwiftSVG,并获得与PocketSVG相同的路径数据,结果相同:

let svgURL = Bundle.main.url(forResource: "fa-mars-stroke-h", withExtension: "svg")!
var bezier = UIBezierPath.pathWithSVGURL(svgURL)!
print(bezier.bounds)

// (0.0085, 0.7200, 68.5542, 41.1379)

let origin = bezier.bounds.origin
let translation = CGAffineTransform(translationX: -origin.x, y: -origin.y)
bezier.apply(translation)
print(bezier.bounds)

// (0.0, -2.7755, 68.5542, 41.1379)

再一次,y分量应为0,但不是。非常奇怪。

一时兴起,我想我会尝试再次应用转换。而且,它有效!

let translation2 = CGAffineTransform(translationX: -bezier.bounds.origin.x, y: -bezier.bounds.origin.y)
bezier.apply(translation2)
print(bezier.bounds)

// (0.0, 0.0, 68.5542491336633, 41.1379438254997)

莫名其妙!我在这里忽略了一些非常基本的东西吗?

2 个答案:

答案 0 :(得分:0)

我和你一样尝试过并在Xcode 8.3.2 / iOS 10中为我工作

enter image description here

答案 1 :(得分:0)

我也遇到了同样的问题,我设法使用下面的代码片段(Swift 5)解决了这个问题。我在有机贝塞尔曲线形状上进行了测试,它可以按预期工作:

extension CGRect {
    var center: CGPoint { return CGPoint(x: midX, y: midY) }
}

extension UIBezierPath {
    func center(inRect rect:CGRect) {
        let rectCenter = rect.center
        let bezierCenter = self.bounds.center
        
        let translation = CGAffineTransform(translationX: rectCenter.x - bezierCenter.x, y: rectCenter.y - bezierCenter.y)
        self.apply(translation)
    }
}

用法示例:

override func viewDidLoad() {
    super.viewDidLoad()

    let bezier = UIBezierPath() // replace this with your bezier object

    let shape = CAShapeLayer()
    shape.strokeColor = UIColor.black.cgColor
    shape.fillColor = UIColor.clear.cgColor
    shape.bounds = self.view.bounds
    shape.position = self.view.bounds.center

    bezier.center(inRect: shape.bounds)
    shape.path = bezier.cgPath
    self.view.layer.addSublayer(shape)
}

它将在屏幕中央显示形状。