如何在参考框架内转换UIBezierPath / CGPath?

时间:2017-06-02 08:57:05

标签: ios core-graphics uibezierpath cgpath

我需要缩放路径,但不是使用路径的边界,而是应该使用更大的,封闭的,任意的矩形来执行变换。 (即“画布”。)

我的问题是如何在不绘制画布的情况下做到这一点。

例如,在下图中:

  • 蓝色方块表示路径的原生矩形(在这种情况下为火箭)。

  • 紫色矩形表示“画布”或父坐标系的界限。

  • 紫色矩形仅用于定位;不被画出来。同样忽略了空格。

  • 我需要缩放画布,并保留变换后的火箭路径(用于剪切操作,缓存等)。即转换后我需要失去紫色矩形。

Rocket

理想情况下,我会使用以下小说:

var canvasPath = UIBezierPath(rect: canvasRect)
canvasPath.append(rocketPath, withName: "rocket")
canvasPath.doSomeTransformOrOther()
let transformedRocketPath = canvasPath.path(forName: "rocket")

可悲的是,即使UIBezierPathCGPath处理了这样的子路径,神奇的追加(:withName :)和path(forName :)方法也不存在。唉!

另一种方法可以是临时为路径添加点,每个画布角一个。然后,转换路径。然后,使用CGPath的(可见的)apply(info:function:)方法遍历路径,重建没有画布点的路径,然后绘制结果。 (是的,通过伏特加。)

有人能提供更理智的解决方案吗?谢谢你的帮助

(对于那些感兴趣的人:这与如何将不规则形状的路径居中的问题有关。紫色矩形代表最小封闭圆的边界。用MEC的坐标系绘制火箭将使火箭看起来更具视觉效果与使用boundingBox相比,居中。)

更多信息:Fitting UIBezierPath/CGPath to circle

1 个答案:

答案 0 :(得分:0)

这是我对问题的最终解决方法:使用“canvas”矩形,它将与路径一起缩放。然后在翻译(缩放)路径时使用画布rect。这样可以保持相对于画布的路径

这样做的一个例子是从SVG获取路径,然后缩放,相对于路径边界相对于SVG的原生维度(“viewbox”)定位路径。这反过来允许在SVG画布中相对定位路径。

extension UIBezierPath
{
    func scaled(usingCanvasSize canvasSize: CGSize,
            scale: CGFloat) -> CGRect
    {
        let canvasRect = CGRect(origin: .zero, size: canvasSize)
        let canvasPath = UIBezierPath(rect: canvasRect)

        let scaleTransform = CGAffineTransform(scaleX: scale, y: scale)
        canvasPath.apply(scaleTransform)
        self.apply(scaleTransform)

        return canvas.bounds
    }
}

// Usage:

let nativeSVGSize: CGSize = ...   // 'viewBox' size of SVG
let path = UIBezierPath(...)      // From SVG, wherever.
let scale: CGFloat = 0.5


// Scale the path, get a "canvas" rect.
let canvasRect = path.scaled(usingCanvasSize: nativeSVGSize,
        scale: scale)

// Use the (scaled) canvas for info about the path from now on.

// e.g. move the path using the center of the canvasRect.

let pathCenter = canvasRect.center
let destCenter = ... 
let movement = CGPoint(x: destCenter.x - pathCenter.x,
        y: destCenter.y - pathCenter.y)

path.apply(CGAffineTransform(translationX: movement.x,
        y: movement.y))