UIBezierPath/Shape 有奇怪的定位和大小调整行为

问题描述:

我正在尝试将一些 SVG 数据(一些中文字符的形状)转换为 UIBezierPath.每个字符由多个 UIBezierPath 组成.这是一个 UIBezierPath 的示例:

I'm trying to convert some SVG data (some shapes for chinese characters) to an UIBezierPath. Each character consists of multiple UIBezierPath. This is an example for one UIBezierPath:

var mypath: UIBezierPath {
    let bp = UIBezierPath()
    bp.move(to: CGPoint(x: 147, y: 32))
    bp.addQuadCurve(to: CGPoint(x: 203, y: 102), controlPoint: CGPoint(x: 181, y: 74))
    bp.addQuadCurve(to: CGPoint(x: 271, y: 189), controlPoint: CGPoint(x: 242, y: 166))
    bp.addQuadCurve(to: CGPoint(x: 274, y: 217), controlPoint: CGPoint(x: 287, y: 204))
    bp.addQuadCurve(to: CGPoint(x: 229, y: 235), controlPoint: CGPoint(x: 258, y: 229))
    bp.addQuadCurve(to: CGPoint(x: 193, y: 235), controlPoint: CGPoint(x: 204, y: 241))
    bp.addQuadCurve(to: CGPoint(x: 190, y: 219), controlPoint: CGPoint(x: 183, y: 231))
    bp.addQuadCurve(to: CGPoint(x: 143, y: 71), controlPoint: CGPoint(x: 199, y: 195))
    bp.addQuadCurve(to: CGPoint(x: 125, y: 33), controlPoint: CGPoint(x: 134, y: 55))
    bp.addCurve(to: CGPoint(x: 147, y: 32), controlPoint1: CGPoint(x: 113, y: 5), controlPoint2: CGPoint(x: 128, y: 9))
    bp.close()
    return bp
}

由于我的最终结果由多个 UIBezierPaths 组成,因此我正在尝试缩放它们:

Since my final result consists of multiple UIBezierPaths I'm trying to scale them:

extension UIBezierPath {
    static func calculateBounds(paths: [UIBezierPath]) -> CGRect {
        let myPaths = UIBezierPath()
        for path in paths {
            myPaths.append(path)
        }
        return (myPaths.bounds)
    }
}

struct ShapeView: Shape {
    let bezier: UIBezierPath
    let pathBounds: CGRect

    func path(in rect: CGRect) -> Path {
        let pointScale = (rect.width >= rect.height) ?
            max(pathBounds.height, pathBounds.width) :
            min(pathBounds.height, pathBounds.width)

        let pointTransform = CGAffineTransform(scaleX: 1/pointScale, y: 1/pointScale)
        let path = Path(bezier.cgPath).applying(pointTransform)

        let multiplier = min(rect.width, rect.height)
        let transform = CGAffineTransform(scaleX: multiplier, y: multiplier)
        return path.applying(transform)
        }
    }

查看:

struct Drawer: View {

    let pathBounds = UIBezierPath.calculateBounds(paths: [mypath]) // to simplify I just add only one shape. Usually there are multiple

    var body: some View {
        ZStack{
            ShapeView(bezier: mypath, pathBounds: pathBounds) 
                .background(Color.red)
            }
        }
    }

这是显示的结果:

如您所见:形状未居中且比屏幕大.我做错了什么,我如何才能使形状居中并完美地适合整个屏幕?

As you can see: The shape is not centered and it's bigger than the screen. What am I doing wrong and how can I achieve that the shapes will be centered and fit perfectly in the entire screen?

我不确定路径转换逻辑是关于什么的(即使你需要它,缺陷也在那里),但只是应用像

I'm not sure about what's that path transforming logic is about (if even you need it the defect is there), but just applying shape like

struct ShapeView: Shape {
    let bezier: UIBezierPath
    let pathBounds: CGRect

    func path(in rect: CGRect) -> Path {
            Path(bezier.cgPath)           // << simple conversion
        }
    }

给出这个(可能是你所期望的):

gives this (probably what you did expect):