在 Core Graphic 中绘制的线条之间创建居中和旋转的 UILabels

Create a centered and rotated UILabels, between drawn lines in Core Graphic

我有以下代码,用于绘制一个圆,里面有线段:

override func draw(_ rect: CGRect) {
    super.draw(rect)
    
    if let context = UIGraphicsGetCurrentContext()
    {
        let width = fmin(self.frame.size.width, self.frame.size.height)
        let offset_x = abs(width - self.frame.size.width)/2
        let offset_y = abs(width - self.frame.size.height)/2
        let padding = CGFloat(0.5)
        let radius_size = (width/2) - (padding*2)
        let circle_width = radius_size/4
        
        context.setStrokeColor(UIColor.black.cgColor)
        
        // Draw a circle
        for i in 0 ..< 4
        {
            let offset = CGFloat(i) * circle_width
            
            context.strokeEllipse(in:
                    CGRect(
                        x: padding + offset + offset_x,
                        y: padding + offset + offset_y,
                        width: (radius_size - offset)*2,
                        height: (radius_size - offset)*2))
        }
        
        let angles: [CGFloat] = [87.0, 112.0, 150]
        let angles2: [CGFloat] = [210.0, 250.0, 330.0]
        let center = CGPoint(x: width/2 + offset_x, y: width/2 + offset_y)
        
        for angle in angles {
            drawLine(context: context, center: center, radius: radius_size, angle: angle)
        }
        
        for angle in angles2 {
            drawLine(context: context, center: center, radius: radius_size * 3 / 4, angle: angle)
        }
        
        context.strokePath()

    }
}

func drawLine(context: CGContext, center: CGPoint, radius: CGFloat, angle: CGFloat) {
    context.move(to: center)
    context.addLine(to: CGPoint(x: center.x + radius * cos(angle * .pi / 180), y: center.y - radius * sin(angle * .pi / 180)))
}

我希望能够在段之间创建一个居中的 UILabel,旋转到正确的角度,我在照片编辑器中做了一个例子:

提前致谢。

我找到了答案:

func drawCurvedText(angle: CGFloat, text: String) {
    drawCurvedString(
      on: textView.layer,
      text: NSAttributedString(
        string: text,
        attributes: [
            NSAttributedString.Key.foregroundColor: UIColor.white,
            NSAttributedString.Key.font: UIFont.systemFont(ofSize: 15)
        ]),
      angle: -angle,
      radius: 130)
    
}

func drawCurvedString(on layer: CALayer, text: NSAttributedString, angle: CGFloat, radius: CGFloat) {
  var radAngle = angle.radians

  let textSize = text.boundingRect(
    with: CGSize(width: .max, height: .max),
    options: [.usesLineFragmentOrigin, .usesFontLeading],
    context: nil)
  .integral
  .size

  let perimeter: CGFloat = 2 * .pi * radius
  let textAngle: CGFloat = textSize.width / perimeter * 2 * .pi

  var textRotation: CGFloat = 0
  var textDirection: CGFloat = 0

  if angle > CGFloat(10).radians, angle < CGFloat(170).radians {
    // bottom string
    textRotation = 0.5 * .pi
    textDirection = -2 * .pi
    radAngle += textAngle / 2
  } else {
    // top string
    textRotation = 1.5 * .pi
    textDirection = 2 * .pi
    radAngle -= textAngle / 2
  }

  for c in 0..<text.length {
    let letter = text.attributedSubstring(from: NSRange(c..<c+1))
    let charSize = letter.boundingRect(
      with: CGSize(width: .max, height: .max),
      options: [.usesLineFragmentOrigin, .usesFontLeading],
      context: nil)
    .integral
    .size

    let letterAngle = (charSize.width / perimeter) * textDirection
    let x = radius * cos(radAngle + (letterAngle / 2))
    let y = radius * sin(radAngle + (letterAngle / 2))

    let singleChar = drawText(
      on: layer,
      text: letter,
      frame: CGRect(
        x: (layer.frame.size.width / 2) - (charSize.width / 2) + x,
        y: (layer.frame.size.height / 2) - (charSize.height / 2) + y,
        width: charSize.width,
        height: charSize.height))
    layer.addSublayer(singleChar)
    singleChar.transform = CATransform3DMakeAffineTransform(CGAffineTransform(rotationAngle: radAngle - textRotation))
    radAngle += letterAngle
  }
}


func drawText(on layer: CALayer, text: NSAttributedString, frame: CGRect) -> CATextLayer {
  let textLayer = CATextLayer()
  textLayer.frame = frame
  textLayer.string = text
    textLayer.alignmentMode = CATextLayerAlignmentMode.center
  textLayer.contentsScale = UIScreen.main.scale
  return textLayer
}