SwiftUI 自定义圆角矩形形状

问题描述 投票:0回答:1

有谁知道如何制作这样的形状吗?

我遵循了苹果教程并想出了这个,但对于我想做的事情来说它似乎过于复杂并且不完美。对我来说,它似乎也很难实施和维护。似乎还有更简单的方法。谢谢你的想法。

struct HexagonParameters {
    
    struct Segment {
        let line: CGPoint
        let curve: CGPoint
        let control: CGPoint
    }
    
    static let adjustment: CGFloat = 0.085
    
    static let topSholdHt = 0.13
    static let botSholdHt = 0.87
    
    static let segments = [
        
        Segment( // top center
                line:    CGPoint(x: 0.80, y: topSholdHt), // top right
                curve:   CGPoint(x: 0.20, y: topSholdHt), // top left
                control: CGPoint(x: 0.50, y: 0.00) // center / peak
            ),
            Segment( // upper left
                line:    CGPoint(x: 0.05, y: 0.20),
                curve:   CGPoint(x: 0.00, y: 0.30),
                control: CGPoint(x: 0.0, y: 0.23)
            ),
            Segment( // lower left
                line:    CGPoint(x: 0.00, y: 0.70),
                curve:   CGPoint(x: 0.05, y: 0.80),
                control: CGPoint(x: 0.00, y: 0.78)
            ),
            Segment( // bottom center
                line:    CGPoint(x: 0.20, y: botSholdHt),
                curve:   CGPoint(x: 0.80, y: botSholdHt),
                control: CGPoint(x: 0.50, y: 1.00)
            ),
            Segment(    // lower right
                line:    CGPoint(x: 0.95, y: 0.80),
                curve:   CGPoint(x: 1.00, y: 0.70),
                control: CGPoint(x: 1.00, y: 0.78)
            ),
            Segment(
                line:    CGPoint(x: 1.00, y: 0.30),
                curve:   CGPoint(x: 0.95, y: 0.20),
                control: CGPoint(x: 1.00, y: 0.23)
            )
    ]
    
}

结构体是这样使用的

struct ContentView: View {
    var body: some View {
        Path { path in
            var width: CGFloat = 300.0
            let height = width
            path.move(
                to: CGPoint(
                    x: width * 0.95,
                    y: height * 0.20
                )
            )
            
            HexagonParameters.segments.forEach { segment in
                path.addLine(
                    to: CGPoint(
                        x: width * segment.line.x,
                        y: height * segment.line.y
                    )
                )
                
                path.addQuadCurve(
                    to: CGPoint(
                        x: width * segment.curve.x,
                        y: height * segment.curve.y),
                    control: CGPoint(
                        x: width * segment.control.x,
                        y: height * segment.control.y
                    )
                )
            }
        }
        .stroke(style: StrokeStyle(lineWidth: 2))
        .foregroundColor(Color.black)
        .padding(.horizontal)

    }
}
swiftui path drawing shapes
1个回答
0
投票

正如我在评论中所说,看起来你自己解决了这个问题,你的代码产生了问题中的形状。

然而,你说你的身材是:

不完美圆润

所以我想知道您是否正在尝试实现更平滑的形状,并且在拐角附近没有倒弧?

假设是这种情况,以下是如何使用自定义解决方案

Shape
。我不会说维护你原来拥有的东西更简单,但至少它展示了一种不同的方法。

struct Lozenge: Shape {
    func path(in rect: CGRect) -> Path {
        let cornerRadius = min(rect.size.width, rect.size.height) * 0.1
        let middleHeight = rect.size.height * 0.15
        let cornerAngleRadians = atan2(rect.size.width, rect.size.height - (2 * middleHeight))
        let cornerAngleDegrees = cornerAngleRadians + 180 / Double.pi

        var path = Path()
        var x = rect.minX
        var y = rect.minY + cornerRadius + middleHeight
        path.move(to: CGPoint(x: x, y: y))

        // Top-left corner
        x += cornerRadius
        path.addArc(
            center: CGPoint(x: x, y: y),
            radius: cornerRadius,
            startAngle: .degrees(-180),
            endAngle: .degrees(-180 + cornerAngleDegrees),
            clockwise: false
        )
        // Middle bump on top
        x = rect.maxX - cornerRadius + (cornerRadius * cos(cornerAngleRadians))
        y = rect.minY + middleHeight + cornerRadius - (cornerRadius * sin(cornerAngleRadians))
        path.addQuadCurve(
            to: CGPoint(x: x, y: y),
            control: CGPoint(x: rect.midX, y: rect.minY - middleHeight)
        )
        // Top-right corner
        x = rect.maxX - cornerRadius
        y = rect.minY + cornerRadius + middleHeight
        path.addArc(
            center: CGPoint(x: x, y: y),
            radius: cornerRadius,
            startAngle: .degrees(-90 + cornerAngleDegrees),
            endAngle: .degrees(0),
            clockwise: false
        )
        // Bottom-right corner
        y = rect.maxY - cornerRadius - middleHeight
        path.addArc(
            center: CGPoint(x: x, y: y),
            radius: cornerRadius,
            startAngle: .degrees(0),
            endAngle: .degrees(cornerAngleDegrees),
            clockwise: false
        )
        // Lower bump on bottom
        x = rect.minX + cornerRadius - (cornerRadius * cos(cornerAngleRadians))
        y = rect.maxY - middleHeight - cornerRadius + (cornerRadius * sin(cornerAngleRadians))
        path.addQuadCurve(
            to: CGPoint(x: x, y: y),
            control: CGPoint(x: rect.midX, y: rect.maxY + middleHeight)
        )
        // Bottom-left corner
        x = rect.minX + cornerRadius
        y = rect.maxY - cornerRadius - middleHeight
        path.addArc(
            center: CGPoint(x: x, y: y),
            radius: cornerRadius,
            startAngle: .degrees(90 + cornerAngleDegrees),
            endAngle: .degrees(180),
            clockwise: false
        )
        path.closeSubpath()
        return path
    }
}

struct ContentView: View {
    var body: some View {
        Lozenge()
            .stroke(lineWidth: 3)
            .frame(width: 300, height: 250)
            .background(.yellow)
    }
}

Lozenge

© www.soinside.com 2019 - 2024. All rights reserved.