Надеюсь, вы понимаете, как работают преобразования CGContext, если нет, изучите это.
Одна из простейших реализаций вашей проблемы выглядит так: текст представляет собой синий прямоугольник, вы хотите нарисовать красный прямоугольник.
Итак, достаточно вычислить преобразование сдвига, затем повернуть на 90. Преобразование сдвига в этом случае - это левый нижний угол синего прямоугольника и в то же время правый нижний угол красного прямоугольника.
Ваш DemoView
может выглядеть так:
class DemoView: NSView {
override func draw(_ rect: NSRect) {
let image = NSImage(named: "test_image.jpg")!
if let context = NSGraphicsContext.current?.cgContext {
context.saveGState()
NSColor.red.set() // just for demo
rect.fill() // just for demo
image.draw(in: rect)
let text: NSString = "Hello World"
let attributes = [
NSAttributedString.Key.foregroundColor: NSColor.white,
NSAttributedString.Key.font: NSFont.systemFont(ofSize: 24)
]
let size = bounds.size
let rotatedTextCenter = CGPoint(x: size.width*0.8, y: size.height/2)
// draw the the circle in desired center to check if text was transformed correctly
drawCircleInView(context: context, center: rotatedTextCenter)
// draw the rotated text so its center fits the circle center
drawAttributedTextInView(text: text, textAttributes: attributes, context: context, viewSize: size, centerInView: rotatedTextCenter)
context.restoreGState()
}
}
func drawCircleInView(context: CGContext, center: CGPoint) {
context.setLineWidth(5)
context.setFillColor(NSColor.red.cgColor)
context.addArc(center: center, radius: 10, startAngle: 0, endAngle: CGFloat.pi*2, clockwise: false)
context.fillPath()
}
func drawAttributedTextInView(text: NSString,
textAttributes: [NSAttributedString.Key:Any],
context: CGContext,
viewSize: CGSize,
centerInView textCenter: CGPoint) {
// we assume everything else was already drawn and context has identity transform for the simplicity
let textSize = text.size(withAttributes: textAttributes)
context.translateBy(x: textCenter.x+textSize.height/2, y: textCenter.y-textSize.width/2)
context.rotate(by: CGFloat.pi / 2)
text.draw(at: .zero, withAttributes: textAttributes)
}
}
В этом коде параметр centerInView
- это центр вашего красного прямоугольника.
Результат выглядит так:
Обратите внимание что мы заполняем весь вид красным цветом, затем визуализируем изображение, затем визуализируем текст. Нет чрезмерного интервала. Если бы он присутствовал, мы бы увидели красные линии под изображением.
Вы можете скачать демо здесь .
И, пожалуйста, не рисуйте все за один звонок draw(_ rect: NSRect)
- попробуйте извлечь по как минимум забавное рисование текста c - это даст вам гораздо больше гибкости в определении переменных задачи.
ОБНОВЛЕНИЕ :
Мне нужен текст быть "перевернутым", чтобы его нижняя сторона была направлена к центру, преобразование может выглядеть следующим образом:
context.translateBy(x: textCenter.x-textSize.height/2, y: textCenter.y+textSize.width/2)
context.rotate(by: -CGFloat.pi / 2)
, а текст будет выглядеть так: