【问题标题】:How to draw smooth curve according to given height如何根据给定的高度绘制平滑曲线
【发布时间】:2020-06-01 09:06:09
【问题描述】:

我想驱动一条平滑的曲线,曲线的 1/3 向外,2/3 向内。这就是我想要实现的目标。

到目前为止,我尝试添加 1 条曲线,例如:

  var height: CGFloat = UIScreen.main.bounds.height / 14
  let centerWidth = self.frame.width / 2 
  let screenView = UIScreen.main.bounds
  let width = (screenView.width - (2*screenView.width/40)) / 10

     path.move(to: CGPoint(x: 0, y: 0)) // start top left
     path.addLine(to: CGPoint(x: (centerWidth - width * 2.5), y: 0)) // the beginning of the trough
           // first curve down
     path.addCurve(to: CGPoint(x: centerWidth   , y: height),
                     controlPoint1: CGPoint(x: (centerWidth - width * 1.33), y: 0), controlPoint2: CGPoint(x: centerWidth - width * 1.33  , y: height))

但是当我尝试这条向外和向内的曲线时,它们的高度相同。所以我改变了它并尝试添加2条曲线:

     path.move(to: CGPoint(x: 0, y: 0)) // start top left
    path.addLine(to: CGPoint(x: (centerWidth - width * 2.5), y: 0)) // the beginning of the trough
        // first curve down
    path.addCurve(to: CGPoint(x: centerWidth - width * 1.33 , y: height/3),
                  controlPoint1: CGPoint(x: (centerWidth - width * 1.33), y: 0), controlPoint2: CGPoint(x: centerWidth - width * 1.33 , y: height/3))

    path.addCurve(to: CGPoint(x: centerWidth, y: height),
                                    controlPoint1: CGPoint(x: centerWidth - width * 1.33 , y: height/3), controlPoint2: CGPoint(x: centerWidth - width , y: height  ))

它类似于我想要的,但连接点看起来不像曲线是一个单一的部分

我尝试了很多东西,但无法准确地画出我想要的东西。那么我怎样才能绘制一条端点高度的 1/3 向外和 2/3 向内看起来像一个整体的曲线。

我对各种想法持开放态度。问候

注意

我正在尝试自定义tabbar 的中心按钮,其高度值为UIScreen.main.bounds.height,宽度为`

let screenView = UIScreen.main.bounds
let width = (screenView.width - (2*screenView.width/40))`

【问题讨论】:

  • 顺便说一句,我建议不要在自己的绘图代码中使用UIScreen.main.bounds。它使它变得非常脆弱,如果它曾经在分屏多任务环境中使用,比如 iPad,就会失败。始终只引用视图的bounds,而不是屏幕尺寸。

标签: ios swift uibezierpath curve


【解决方案1】:

当我查看您的设计师的渲染图时,如果您将其分解为两条单独的贝塞尔曲线,关键的观察结果是顶部 ⅓ 曲线是对称的(相对于自身而言),底部 ⅔ 曲线也是如此。对于对称的贝塞尔曲线,四边形贝塞尔曲线更容易处理。

为了使拐点无缝,您需要确保两个控制点(一个用于拐点上方的四边形贝塞尔曲线,另一个用于拐点下方的四边形贝塞尔曲线)与拐点本身共线.例如:

需要一点三角函数来计算这些控制点的位置,例如

let center = CGPoint(x: view.bounds.midX, y: 200)
let radius: CGFloat = 140
let curveOffsetBottom: CGFloat = 30
let curveOffsetInflection: CGFloat = 50

greenCircularShapeLayer.path = UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: 2 * .pi, clockwise: true).cgPath

let h = radius + curveOffsetBottom + 50

let curveBottom = CGPoint(x: center.x,
                          y: center.y + radius + curveOffsetBottom)

let y0 = radius + curveOffsetBottom - h * 2 / 3
let t0 = asin(y0 / (radius + curveOffsetInflection))
let x0 = y0 / tan(t0)

let inflectionPoint = CGPoint(x: center.x - x0, y: center.y + y0)

let t1 = atan((curveBottom.x - inflectionPoint.x) / (curveBottom.y - inflectionPoint.y))

let t2 = 2 * (.pi / 2 - t1)

let x2 = (curveBottom.y - inflectionPoint.y) / tan(t2)
let x1 = x2 / 2

let cp1 = CGPoint(x: inflectionPoint.x - x1, y: curveBottom.y - h)
let cp2 = CGPoint(x: inflectionPoint.x + x2, y: curveBottom.y)

let curveTop = CGPoint(x: cp1.x - cp1.distance(to: inflectionPoint), y: curveBottom.y - h)

let path = UIBezierPath()
path.move(to: curveTop)
path.addQuadCurve(to: inflectionPoint, controlPoint: cp1)
path.addQuadCurve(to: curveBottom, controlPoint: cp2)

path.addLine(to: CGPoint(x: view.bounds.maxX, y: path.currentPoint.y))
path.addLine(to: CGPoint(x: view.bounds.maxX, y: view.bounds.maxY))
path.addLine(to: CGPoint(x: view.bounds.minX, y: view.bounds.maxY))
path.addLine(to: CGPoint(x: view.bounds.minX, y: curveTop.y))
path.close()

blackCurveShapeLayer.path = path.cgPath

在哪里

extension CGPoint {
    func distance(to point: CGPoint) -> CGFloat {
        hypot(point.x - x, point.y - y)
    }
}

【讨论】:

  • 我确实尝试过但收到错误 Value of type 'CGPoint' has no member 'distance'cp1.distance 函数是什么?
  • @OmerTekbiyik - 抱歉,这是我在CGPoint 上使用的一个小扩展,它只是调用hypot 来计算两点之间的距离。更新了答案以包括这一点。上面我用它来保证起点和控制点的距离和拐点的距离一样。
  • 谢谢。实际上,我正在尝试自定义选项卡栏,哪个中心按钮需要查看您绘制的内容,但是当我尝试编写代码时,一些 x 点超出了屏幕,因此无法绘制它
  • @OmerTekbiyik 没关系。您可以移动圆形图层的位置并根据需要更改各种常量。无论大小和位置如何,这都应该适当地呈现。此外,不要迷失在所有这些实施细节中。重点是用两个控制点与端点等距且与拐点共线的四边形贝塞尔曲线来达到设计者的效果。
  • 谢谢你的建议,我要试试@Rob
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-09
  • 2012-05-16
  • 2021-02-18
  • 1970-01-01
  • 2017-06-10
  • 2017-01-14
相关资源
最近更新 更多