在 Core Graphic 中绘制的线条之间创建一个居中旋转的 UILabel
Posted
技术标签:
【中文标题】在 Core Graphic 中绘制的线条之间创建一个居中旋转的 UILabel【英文标题】:Create a centered and rotated UILabels, between drawn lines in Core Graphic 【发布时间】:2020-08-26 20:35:24 【问题描述】:我有下面的代码,画一个圆圈,里面有段:
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 段之间创建一个居中,并旋转到直角,我在照片编辑器中做了一个示例:
提前致谢。
【问题讨论】:
我猜你可能想尝试绘制文本而不是创建 UILabel。我认为这可能更容易。 @Max 谢谢,任何代码示例都将不胜感激。 ***.com/a/32785652/1630618 实际上,如果您使用 CATextLayer 对象,按照您显示的方式放置它们是微不足道的。 【参考方案1】:我找到了答案:
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
【讨论】:
我在评论中建议使用文本层。以上是关于在 Core Graphic 中绘制的线条之间创建一个居中旋转的 UILabel的主要内容,如果未能解决你的问题,请参考以下文章