剪裁曲线形状的贝塞尔路径

4
我正在使用Swift在手机UI中创建自定义按钮,并需要将按钮底部剪裁成凸形。问题是它应该是完美的,底部曲线应该与更大的按钮匹配。我尝试了不同的方法,但没有得到完美的结果。如下图所示:
  1. Using rounded corners

    if buttonDirection == 0 {
        path = UIBezierPath(roundedRect: rect, byRoundingCorners:[UIRectCorner.topLeft, .topRight], cornerRadii: CGSize(width: self.bounds.width/2, height: 0))
        path.close()  
    }
    
  2. Create whole path without rounded curve using QuardCurve // still bottom part not inverse curve plus corner are also not smooth as 1

     if buttonDirection == 0 {
           //path = UIBezierPath(roundedRect: rect, byRoundingCorners:[UIRectCorner.topLeft, .topRight], cornerRadii: CGSize(width: self.bounds.width/2, height: 0))
          //path.close()
            let curve = UIBezierPath()
            curve.move(to: CGPoint(x: 0, y: self.bounds.height))
            curve.addLine(to:CGPoint(x: 0, y: self.bounds.width/3))
            curve.addQuadCurve(to: CGPoint(x: self.bounds.width, y: self.bounds.width/3), controlPoint: CGPoint(x: self.bounds.width/2, y: -5))
            curve.addLine(to: CGPoint(x: self.bounds.width, y: self.bounds.height))
            curve.addQuadCurve(to: CGPoint(x: 0, y: self.bounds.height), controlPoint: CGPoint(x: self.bounds.width/2, y: self.bounds.width - 10))
            UIColor.black.setFill()
            curve.fill()
        }
    
  3. Create the path from 1 and then just Clip QuardCurve

    if buttonDirection == 0 {
        path = UIBezierPath(roundedRect: rect, byRoundingCorners:[UIRectCorner.topLeft, .topRight], cornerRadii: CGSize(width: self.bounds.width/2, height: 0))
        path.close()
        path.move(to: CGPoint(x: 0, y: self.bounds.height))
        path.addQuadCurve(to: CGPoint(x: self.bounds.width, y: self.bounds.height), controlPoint: CGPoint(x: self.bounds.width/2, y: self.bounds.height/2))
        path.addClip()
        UIColor.black.setFill()
        path.fill()
    } 
    
我尝试了很多其他方法,但没有得到我想要的结果。我的目标是从第一条路径中简单地剪切底部曲线,就像如何从另一条路径中剪切一条路径一样(在阅读苹果文档后,我也知道可以使用path.reverse())。
这是所有按钮在一个图片中,当你点击按钮时,比如说vol+,它会改变颜色。
PS:编辑了原问题,因为图片很混乱,我找到了一个解决方案,但仍然想知道是否有更好的解决方案只需要一条路径和平滑的边缘。

我已经阅读了你的问题,但是我不明白你所说的“剪辑反曲线”的意思。你的图片也展示了大量的图形,你是在特别讨论“如何创建一个圆形并从中切出另一个圆形”吗? - Mike 'Pomax' Kamermans
请检查第四张图片中的Vol+按钮,您是否看到底部的曲线被切成了圆形? - Iraniya Naynesh
实际上,它们都是音量+、音量-、频道+和频道-按钮,但谢谢,我会更新问题的 :-) - Iraniya Naynesh
为什么不使用弧线而不是曲线呢?您知道您的圆的半径,因此使用实际的圆弧比手动近似好曲率要容易得多。只需在主圆上以适当的半径为中心使用单个2pi弧作为剪切路径,这应该就是您需要做的全部了。 - Mike 'Pomax' Kamermans
你的网站 https://pomax.github.io/bezierinfo/ 关于贝塞尔曲线非常棒 :-) 两种方法之间是否存在任何性能问题?quardCurve 只使用一个控制点,而弧线在内部处理时似乎仍然将其用作圆心,对吗? - Iraniya Naynesh
显示剩余3条评论
1个回答

0

以下方法可行,但如果有更好的解决方案,请发帖分享。 基本上我在这里所做的是先将整个按钮与底部部分剪切为凸形,使用addLines和Quardcurve在底部创建曲线,然后使用bezier roundedRect初始化创建新路径,包括右上角和左上角。

if buttonDirection == 0 {
     let curve = UIBezierPath()
     curve.move(to: CGPoint(x: 0, y: self.bounds.height))
     curve.addLine(to: CGPoint(x: 0, y: 0))
     curve.addLine(to: CGPoint(x: self.bounds.width, y: 0))
     curve.addLine(to: CGPoint(x: self.bounds.width, y: self.bounds.height))
     curve.addQuadCurve(to: CGPoint(x: 0, y: self.bounds.height), controlPoint: CGPoint(x: self.bounds.width/2, y: self.bounds.height - self.bounds.height/4))
     curve.close()
     curve.addClip()
     path = UIBezierPath(roundedRect: rect, byRoundingCorners:[UIRectCorner.topLeft, .topRight], cornerRadii: CGSize(width: self.bounds.width/2, height: 0))
     path.close()
} 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接