如何根据给定的高度绘制平滑曲线

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

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

enter image description here

到目前为止,我尝试通过添加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  ))

它与我想要的相似,但是接合点看起来不像曲线enter image description here

[我已经尝试了很多东西,但无法画出我想要的东西。所以,我该如何绘制一条曲线,使端点高度的1/3向外而2/3向内看起来像一块。

我愿意接受各种各样的想法。问候

ios swift uibezierpath curve
1个回答
0
投票

[当我查看设计师的渲染时,如果将其分成两条单独的贝塞尔曲线,则主要观察结果是顶部⅓曲线与底部as曲线是对称的(相对于自身)。对于对称的贝塞尔曲线,四边贝塞尔曲线更易于处理。

并且要使拐点无缝,您需要确保两个控制点(一个用于拐点上方的方形贝塞尔曲线,另一个用于拐点下方的方形贝塞尔曲线)与拐点共线。例如:

enter image description here

例如,需要一些三角函数才能确定这些控制点的位置

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)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.