简体   繁体   English

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

[英]How to draw smooth curve according to given height

I want to drive a smooth curve that curve's 1/3 is outward 2/3 is inward.This is what I want to achieve.我想驱动一条平滑的曲线,曲线的 1/3 向外,2/3 向内。这就是我想要实现的。

在此处输入图像描述

So far, I tried this with adding 1 curve like:到目前为止,我尝试添加 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))

But when I try this outward and inward curve's have same height.但是当我尝试这条向外和向内的曲线时,它们的高度相同。 So I changed it and tried adding 2 curve like:所以我改变了它并尝试添加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  ))

It similar to what I want but junction point doesnt look the curve is a single piece它类似于我想要的,但连接点看起来不像曲线是单件在此处输入图像描述

I have tried so many things but cant draw what I want exacly.So How can I draw a curve that endpoint height's 1/3 gonna be outward and 2/3 inward that looks like a one piece.我已经尝试了很多东西,但无法准确地画出我想要的东西。所以我怎样才能画出一条曲线,端点高度的 1/3 向外,2/3 向内,看起来像一个整体。

I'm open to all kinds of ideas to draw.Regards我对各种想法持开放态度。问候

NOTE笔记

I'm trying to customize tabbar 's center button which height value is UIScreen.main.bounds.height and width is `我正在尝试自定义tabbar的中心按钮,其高度值为UIScreen.main.bounds.height且宽度为 `

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

As I look at your designer's rendering, if you are breaking this into two separate Bézier curves, the key observation is that the top ⅓ curve is symmetrical (with respect to itself) as is the bottom ⅔ curve.当我查看您的设计师的渲染图时,如果您将其分解为两条单独的贝塞尔曲线,关键的观察结果是顶部 ⅓ 曲线是对称的(相对于自身而言),底部 ⅔ 曲线也是如此。 And for symmetrical Bézier curves, a quad Bézier is easier to deal with.对于对称的贝塞尔曲线,四边形贝塞尔曲线更容易处理。

And to make the inflection point seamless, you'll want to ensure that two control points (one for the quad Bézier above the inflection point, the other for the quad Bézier below the inflection point) are collinear with the inflection point itself.为了使拐点无缝,您需要确保两个控制点(一个用于拐点上方的四边形贝塞尔曲线,另一个用于拐点下方的四边形贝塞尔曲线)与拐点本身共线。 Eg:例如:

在此处输入图像描述

It takes a little trigonometry to figure out the placement of these control points, eg需要一点三角函数来计算这些控制点的位置,例如

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

Where在哪里

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM