UIBezierPath, как нарисовать «квадратную кривую»

#swift #drawing #uibezierpath #curve

#быстрый #рисование #uibezierpath путь #кривая

Вопрос:

Я пытаюсь нарисовать фигуру, используя UIBezierPath, но я не совсем понимаю, как нужно использовать «addQuadCurve», я рисую первую кривую слева от центрального отверстия, но не могу понять, как нарисовать правый край.

Что я делаю не так?

Результат, который нужен: результат, который нуженМой результат:мой результат

Код формы:

 class CustomShapeOfBottomOne: UIView {

    // init the view with a rectangular frame
    override init(frame: CGRect)
    {
      super.init(frame: frame)
      backgroundColor = UIColor.clear
    }
    // init the view by deserialisation
    required init?(coder aDecoder: NSCoder)
    {
      super.init(coder: aDecoder)
      backgroundColor = UIColor.clear
    }

    override func draw(_ rect: CGRect)
    {
        
        let fillColor = UIColor(red: 0.118, green: 0.118, blue: 0.149, alpha: 1.000)
        
        let path = UIBezierPath()
        let viewWidth = frame.width
        let viewHeight = frame.height - 20
        
        path.move(to: CGPoint(x: (viewWidth - viewWidth)   10, y: 0))
        
        path.addLine(to: CGPoint(x: (viewWidth / 2) - 35 - 10, y: 0))
        
        // center left edge
        
        path.addQuadCurve(to: CGPoint(x: (viewWidth / 2 ) - 35, y: (11/2.0)), controlPoint: CGPoint(x: (viewWidth / 2 ) - 35, y: 0))
        // end left edge
        
        path.addArc(withCenter: CGPoint(x: viewWidth / 2, y: 0), radius: 35, startAngle: CGFloat(Double.pi), endAngle: CGFloat(Double.pi * Double.pi), clockwise: false)
        
        // How to draw this curve?
        
        // center right edge
//        path.addQuadCurve(to: CGPoint(x: (viewWidth / 2 )   35   10 , y: 0), controlPoint: CGPoint(x: (viewWidth / 2 )   35 - 10, y: 10))
        
        
        // end right edge
        
        path.addLine(to: CGPoint(x: viewWidth - 10, y: 0))
                
        path.addArc(withCenter: CGPoint(x: viewWidth - 10, y: (viewHeight - viewHeight)   10),
                    radius: 10,
                    startAngle: CGFloat(Double.pi / 2), // 90 degree
                    endAngle: CGFloat(0), // 0 degree
                clockwise: true)
        
        path.addLine(to: CGPoint(x: viewWidth, y: (viewHeight - viewHeight)   viewHeight   10))
        
        path.addArc(withCenter: CGPoint(x:  viewWidth - 10, y: (viewHeight - viewHeight)   viewHeight   10),
                    radius: 10,
                    startAngle: CGFloat(0), // 360 degree
                endAngle: CGFloat((3 * Double.pi) / 2 ), // 270 degree
                clockwise: true)
        
        path.addLine(to: CGPoint(x: viewWidth - 10, y: (viewHeight - viewHeight)   viewHeight   10   10))
        path.addLine(to: CGPoint(x: (viewWidth - viewWidth)   10, y: (viewHeight - viewHeight)   viewHeight   10   10))
        
        path.addArc(withCenter: CGPoint(x: (viewWidth - viewWidth)   10, y: (viewHeight - viewHeight)   viewHeight   10),
                    radius: 10,
                    startAngle: CGFloat((3 * Double.pi) / 2), // 270 degree
                    endAngle: CGFloat(Double.pi ), // 180 degree
                clockwise: true)
        
        path.addLine(to: CGPoint(x: viewWidth - viewWidth, y: (viewHeight - viewHeight)   viewHeight   10))
        path.addLine(to: CGPoint(x: viewWidth - viewWidth, y: (viewHeight - viewHeight)   10))
        
        path.addArc(withCenter: CGPoint(x: (viewWidth - viewWidth)   10, y: (viewHeight - viewHeight)   10),
                    radius: 10,
                    startAngle: CGFloat(Double.pi), // 180 degree
                endAngle: CGFloat(Double.pi / 2 ), // 90 degree
                clockwise: true)
        
        path.close()
        fillColor.setFill()
        path.fill()
    }
}
 

Покажите мне пример, что нужно изменить, или объясните мне, где я допустил ошибку?

Ответ №1:

Я решил эту проблему, используя «addCurve» вместо «addQuadCurve». код, который я заменяю

От:

 // center left edge
        
        path.addQuadCurve(to: CGPoint(x: (viewWidth / 2 ) - 35, y: (11/2.0)), controlPoint: CGPoint(x: (viewWidth / 2 ) - 35, y: 0))
        // end left edge
        
        path.addArc(withCenter: CGPoint(x: viewWidth / 2, y: 0), radius: 35, startAngle: CGFloat(Double.pi), endAngle: CGFloat(Double.pi * Double.pi), clockwise: false)
        
        // How to draw this curve?
        
        // center right edge
//        path.addQuadCurve(to: CGPoint(x: (viewWidth / 2 )   35   10 , y: 0), controlPoint: CGPoint(x: (viewWidth / 2 )   35 - 10, y: 10))
        
        
        // end right edge
 

Для:

// центральный левый край

     path.addCurve(to: CGPoint(x: (viewWidth / 2) - 35.9, y: 10), controlPoint1: CGPoint(x: (viewWidth / 2) - 35, y: 0), controlPoint2: CGPoint(x: (viewWidth / 2) - 35, y: 10))
    // end left edge
    
    path.addArc(withCenter: CGPoint(x: viewWidth / 2, y: 0), radius: 36.5, startAngle: CGFloat(Double.pi), endAngle: CGFloat(2 * Double.pi), clockwise: false)
    
    // How to draw this curve?
    
    // center right edge
    path.addCurve(to: CGPoint(x: (viewWidth / 2)   35   8, y: 0), controlPoint1: CGPoint(x: (viewWidth / 2)   36, y: 10), controlPoint2: CGPoint(x: (viewWidth / 2)   35, y: 0))

    // end right edge
 

Результат:
Конечный результат

Комментарии:

1. Это выглядит не совсем правильно. Если вы внимательно посмотрите на «отступ» в верхнем центре вашей фигуры, там есть пара тонких шипов. Это, вероятно, результат того, что ваша дуга проходит весь путь до y = 0. Вы должны понизить положение Y вашей дуги на 10 пунктов до y = 10. (вы хотите, чтобы начальная и конечная точки вашей дуги совпадали с конечными точками ваших 2 кривых.)

2. Разница между addCurve() и addQuadCurve() довольно тонкая. addQuadCurve() добавляет квадратичную кривую Безье с одной промежуточной контрольной точкой и addCurve() добавляет кубическую кривую Безье с 2 промежуточными контрольными точками. Оба начинаются с текущей точки и заканчиваются в указанной конечной точке.

3. Спасибо за помощь, я меняю положение Y на 10, а радиус окружности на 36,5, и все шипы были удалены 🙂

Ответ №2:

Нарисуйте схему того, что вы пытаетесь сделать на миллиметровой бумаге. Нарисуйте все линии, четырехугольные кривые и сегменты дуги, которые вы используете.

Я думаю, вы обнаружите, что ваша дуга проходит до самого верха вашей фигуры, покрывая нужный вам закругленный угол. Вам нужно переместить положение Y вашей дуги вниз так, чтобы начальная и конечная точки дуги начинались на концах ваших внутренних закругленных углов, которые немного ниже вершины вашей фигуры.

Комментарии:

1. Вы правы! Я решил проблему, и через несколько минут я опубликую свой код, если вы знаете, как более элегантно решить эту проблему, дайте мне знать.