-2

我需要在我的 collectionView 部分有一个边框和圆角半径。因此,如果它是第一行,我需要绘制一个无底矩形层。如果它是最后一行,我将绘制一个裸照层。

如何使用贝塞尔路径实现我的绘图?

在此处输入图像描述

已编辑

我已经使用了这个代码,它可以工作。但我无法为裸照矩形创建方法。

extension CGMutablePath {
 static func bottomlessRoundedRect(in rect: CGRect, radius: CGFloat) -> CGMutablePath {
    let path = CGMutablePath()
    path.move(to: CGPoint(x: rect.minX, y: rect.maxY))
    path.addArc(tangent1End: CGPoint(x: rect.minX, y: rect.minY), tangent2End: CGPoint(x: rect.maxX, y: rect.minY), radius: radius)
    path.addArc(tangent1End: CGPoint(x: rect.maxX, y: rect.minY), tangent2End: CGPoint(x: rect.maxX, y: rect.maxY), radius: radius)
    path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
    return path
 }
}

let layer = CAShapeLayer()
layer.lineWidth = 1
layer.strokeColor = UIColor.black.cgColor
layer.fillColor = nil
layer.path = CGMutablePath.bottomlessRoundedRect(in: testView.bounds.insetBy(dx: 1, dy: 1), radius: 18)
view.layer.insertSublayer(layer, at: 0)

view.layoutIfNeeded()

这是裸照矩形的方法,它无法正常工作。

static func toplessRoundedRect(in rect: CGRect, radius: CGFloat) -> CGMutablePath {
    let path = CGMutablePath()
    path.move(to: CGPoint(x: rect.minX, y: rect.minY))
    path.addArc(tangent1End: CGPoint(x: rect.minX, y: rect.minY), tangent2End: CGPoint(x: rect.minX, y: rect.maxY), radius: radius)

    path.addArc(tangent1End: CGPoint(x: rect.minX, y: rect.maxY), tangent2End: CGPoint(x: rect.maxX, y: rect.minY), radius: radius)
    path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
    return path
}

这就是结果。 在此处输入图像描述

请帮我做一个正确的裸照直肠。(我之前没有用过绘图)

答案

static func toplessRoundedRect(in rect: CGRect, radius: CGFloat) -> CGMutablePath {
    let path = CGMutablePath()
    path.move(to: CGPoint(x: rect.minX, y: rect.minY))
    path.addArc(tangent1End: CGPoint(x: rect.minX, y: rect.maxY), tangent2End: CGPoint(x: rect.maxX, y: rect.maxY), radius: radius)

    path.addArc(tangent1End: CGPoint(x: rect.maxX, y: rect.maxY), tangent2End: CGPoint(x: rect.maxX, y: rect.minY), radius: radius)
    path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
    return path
}
4

2 回答 2

3

把它画出来。圆角矩形是一系列与给定半径的四分之一圆弧相连的线段。(拐角半径。)

iOS 使用不同的坐标系,具体取决于你的绘图方式(Core Graphics 使用 LLO,或左下原点,而 UIKit/Core Animation 使用 ULO,或左上原点。)

看起来 CAShapeLayers 中使用的 CGPath 使用 ULO(左上角原点)坐标,其中 0,0 位于左上角,向下时 Y 增加。

您的 bottomlessRoundedRect() 函数以这行代码开头:

path.move(to: CGPoint(x: rect.minX, y: rect.maxY))

移动到矩形的左下角(最大 Y)位置开始。

注释整个函数,这是它的作用:

static func bottomlessRoundedRect(in rect: CGRect, radius: CGFloat) -> CGMutablePath {
    let path = CGMutablePath()
    //Move to the lower left corner of the rect (starting point)
    path.move(to: CGPoint(x: rect.minX, y: rect.maxY))
    
    //Draw a line from the starting point to the beginning of the arc in the
    //top left corner, and draw the top left rounded corner
    path.addArc(tangent1End: CGPoint(x: rect.minX, y: rect.minY),
                tangent2End: CGPoint(x: rect.maxX, y: rect.minY),
                radius: radius)
    
    //Draw a line from the top left corner to the begnning of the top right
    //arc, and the top right corner arc
    path.addArc(tangent1End: CGPoint(x: rect.maxX, y: rect.minY),
                tangent2End: CGPoint(x: rect.maxX, y: rect.maxY),
                radius: radius)
    
    //Draw a final line from the end of the top right corner arc to
    //the bottom right corner
    path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
    return path
}

画出你的整个矩形。选择你的拐角半径。绘制一个角由角半径插入的内部矩形。在你的内部矩形的角上画圆,并注意它们是如何与你的外部矩形的边相交的。

现在把它放在一起。

打开贝塞尔路径。移动到您想要的起点。在下边创建一条线,减去你的拐角半径。以完成该角所需的角度开始和结束绘制一个 1/4 圆弧。绘制下一条线段。再画一条弧线。画出你的最后一条线段。

函数的注释版本toplessRoundedRect()如下所示:

static func toplessRoundedRect(in rect: CGRect, radius: CGFloat) -> CGMutablePath {
    let path = CGMutablePath()
    
    //Move to the top left corner.
    path.move(to: CGPoint(x: rect.minX, y: rect.minY))
    
    //Draw a line from the top left corner to the begnning of the bottom left
    //rounded corner, plus the bottom left rounded corner
    path.addArc(tangent1End: CGPoint(x: rect.minX, y: rect.maxY),
                tangent2End: CGPoint(x: rect.maxX, y: rect.maxY),
                radius: radius)
    
    //Draw a line from the end of the bottom left rounded corner to the beginning
    //of the bottom right rounded corner, plus the bottom right rounded corner
    path.addArc(tangent1End: CGPoint(x: rect.maxX, y: rect.maxY),
                tangent2End: CGPoint(x: rect.maxX, y: rect.minY),
                radius: radius)
    
    //Draw a line from the end of the bottom right rounded corner
    //to the top right corner.
    path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
    return path
}
于 2021-02-01T20:04:22.130 回答
2

这里有一个提示:一次处理一行代码。

CGMutablePath将您的扩展名更改为:

extension CGMutablePath {
    static func bottomlessRoundedRect(in rect: CGRect, radius: CGFloat) -> CGMutablePath {
        let path = CGMutablePath()
        // 1
        path.move(to: CGPoint(x: rect.minX, y: rect.maxY))
        // 2
        //path.addArc(tangent1End: CGPoint(x: rect.minX, y: rect.minY), tangent2End: CGPoint(x: rect.maxX, y: rect.minY), radius: radius)
        // 3
        //path.addArc(tangent1End: CGPoint(x: rect.maxX, y: rect.minY), tangent2End: CGPoint(x: rect.maxX, y: rect.maxY), radius: radius)
        // 4
        //path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
        return path
    }
}

当您运行您的应用程序时,只会1执行路径的一部分。你不会看到任何东西,因为到目前为止你所做的只是move到了一定程度。

现在,取消注释该2部分。运行你的代码,看看结果如何。

取消注释该3部分。运行你的代码,看看结果如何。

取消注释该4部分。运行你的代码,看看结果如何。

到目前为止,您应该对代码在做什么有了一个很好的了解,并且创建您的toplessRoundedRectfunc 应该是小菜一碟。

于 2021-02-01T21:40:58.137 回答