1

The question was asked for BezierPath but now I not necessary to be with bezier it can be with core graphics also.

I am trying to draw curved text (shape it could be started as straight line to circle) and I saw CoreText allow us to draw text on UIBezierPath path. So I tried to draw a straight line and curved it into circle by given bend factor value. It should straight line if value is zero and if its positive bend line to down side else bend the line to up side [text will draw along this path.]

Did a way to bend straight line with given 'bend factor' into circle with UIBezierPath like this ?

enter image description here

i'have tried with way actually I am not convinced... Draw curve with 2 control points, if bend factor is 0 draw straight line else curve line while curve != half circle then updating path with half circle to complete path into a circle if bend factor is positive and doing reverse if bend factor is negative value it looks like straight line converts into circle but this not a good method to do this..For better understanding please take a look here

For example:

    let r = textFXmodel.radius // This is bend factor
    
    if r != 0.0 { // If bend factor is equals to zero draw straight line

        let positiveR = abs(r)
        let fullSize = self.bounds.size
        var curvedLinePath = UIBezierPath()

        let insetRect = self.bounds.insetBy(dx: 10, dy: 10)
        let maximumValue = Float(insetRect.size.width / 2)
        let minimumValue = -Float(insetRect.size.width / 2)

        if r >= 0.0 { // If bend factor 'r' is positive value
            if r <= CGFloat(maximumValue / 2) { // If bend factor 'r' less then half of circle ⌢

                // Draw curved line and bend it from control points
                let controlPoint1 = CGPoint(x: fullSize.width / 2 - (r + r * 0.2), y: fullSize.height / 2 - (r * 1.5))
                let controlPoint2 = CGPoint(x: fullSize.width / 2 + (r + r * 0.2), y: fullSize.height / 2 - (r * 1.5))
                let curveStartPoint = CGPoint(x: r, y: fullSize.height / 2)
                let curveEndPoint = CGPoint(x: fullSize.width - r, y: fullSize.height / 2)
                curvedLinePath.move(to: curveStartPoint)
                curvedLinePath.addCurve(to: curveEndPoint, controlPoint1: controlPoint1, controlPoint2: controlPoint2)
                
            } else { // bend factor 'r' is greater or equal to half circle so remove curved line and draw half circle path

                let scaledRadius: CGFloat = r - 60
                let centerPoint = CGPoint(x: fullSize.width / 2, y: fullSize.height / 2)
                let startAngel = CGFloat.pi - (scaledRadius * 0.023)
                let endAngle = (CGFloat.pi * 2) + (scaledRadius * 0.023)
                curvedLinePath.removeAllPoints()
                curvedLinePath = UIBezierPath(arcCenter: centerPoint, radius: (fullSize.width / 4), startAngle: startAngel, endAngle: endAngle, clockwise: true)
            }
            
        } else {
            
            if r >= CGFloat(minimumValue / 2) {

                let controlPoint1 = CGPoint(x: fullSize.width / 2 - (positiveR + positiveR * 0.2), y: fullSize.height / 2 + (positiveR * 1.5))
                let controlPoint2 = CGPoint(x: fullSize.width / 2 + (positiveR + positiveR * 0.2), y: fullSize.height / 2 + (positiveR * 1.5))
                let curveStartPoint = CGPoint(x: positiveR, y: fullSize.height / 2)
                let curveEndPoint = CGPoint(x: fullSize.width - positiveR, y: fullSize.height / 2)
                curvedLinePath.move(to: curveStartPoint)
                curvedLinePath.addCurve(to: curveEndPoint, controlPoint1: controlPoint1, controlPoint2: controlPoint2)
                
            } else {

                let scaledRadius: CGFloat = positiveR - 60
                let centerPoint = CGPoint(x: fullSize.width / 2, y: fullSize.height / 2)
                let startAngel = CGFloat.pi + (scaledRadius * 0.023)
                let endAngle = (CGFloat.pi * 2) - (scaledRadius * 0.023)
                curvedLinePath.removeAllPoints()
                curvedLinePath = UIBezierPath(arcCenter: centerPoint, radius: (fullSize.width / 4), startAngle: startAngel, endAngle: endAngle, clockwise: false)
            }
        }

      // and here goes drawing code...

My code works like this it looks like line break at half of way (:

If you have a way to draw text like this without Bezierpath or CoreText please share it with me. I've googled a lot and I read all answers about this topic and no one helped me even this answer, and this

UPDATE:- In this version line segment will bend in same center but this also not real circle it looks like drop shape

private func updatePath(withRadius radius: CGFloat) -> UIBezierPath {
    var curveStartPoint: CGPoint = .zero
    var curveEndPoint: CGPoint = .zero
    var controlPoint1: CGPoint = .zero
    var controlPoint2: CGPoint = .zero
    if radius > 0.0 {
        controlPoint1 = CGPoint(x: size.width / 2 - (radius + radius * 0.2), y: size.height / 2 - radius)
        controlPoint2 = CGPoint(x: size.width / 2 + (radius + radius * 0.2), y: size.height / 2 - radius)
        curveStartPoint = CGPoint(x: radius, y: size.height / 2 + (radius * 0.5))
        curveEndPoint = CGPoint(x: size.width - radius, y: size.height / 2 + (radius * 0.5))
    } else {
        let positateR: CGFloat = abs(radius)
        controlPoint1 = CGPoint(x: size.width / 2 - (positateR + positateR * 0.2), y: size.height / 2 + positateR)
        controlPoint2 = CGPoint(x: size.width / 2 + (positateR + positateR * 0.2), y: size.height / 2 + positateR)
        curveStartPoint = CGPoint(x: positateR, y: size.height / 2 + (radius * 0.5))
        curveEndPoint = CGPoint(x: size.width - positateR, y: size.height / 2 + (radius * 0.5))
    }

    let drawingPath = UIBezierPath()
    drawingPath.move(to: curveStartPoint)
    drawingPath.addCurve(to: curveEndPoint, controlPoint1: controlPoint1, controlPoint2: controlPoint2)
    return drawingPath
}
Coder ACJHP
  • 1,940
  • 1
  • 20
  • 34

0 Answers0