首页 > 解决方案 > UIBezierPath / Shape 有奇怪的定位和调整大小行为

问题描述

我正在尝试将一些 SVG 数据(汉字的一些形状)转换为 UIBezierPath。每个字符由多个 UIBezierPath 组成。这是一个 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 组成,我正在尝试缩放它们:

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)
            }
        }
    }

这是显示的结果:

在此处输入图像描述

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

标签: swiftuiuibezierpath

解决方案


我不确定路径转换逻辑是什么(如果你需要它,缺陷就在那里),但只是应用形状像

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

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

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

演示


推荐阅读