在NSImage的右侧绘制文字 - 不需要的间距

问题描述 投票:0回答:1

我使用下面的代码在图片的右侧绘制文字。

         im.lockFocus()
         if let context = NSGraphicsContext.current?.cgContext {
         context.saveGState()
         let size = text.size(withAttributes: textFontAttributes)
         context.translateBy(x: imageRect.width-size.height, y: (imageRect.height - size.width) / 2)
         context.rotate(by: CGFloat.pi / 2)
         text.draw(at: .zero, withAttributes: textFontAttributes)
         context.restoreGState()
         im.unlockFocus()

如你所见,从右侧开始有一些过大的间距,我该如何解决?

enter image description here

更新。

class DemoView: NSView {
    override func draw(_ rect: NSRect) {

        // .. your drawing code here

        NSColor.red.set()  // just for demo
        rect.fill()        // just for demo

        if let context = NSGraphicsContext.current?.cgContext {
            context.saveGState()

            let text: NSString = "Hello World"
            let attributes = [
                NSAttributedString.Key.foregroundColor: NSColor.white, 
                NSAttributedString.Key.font: NSFont.systemFont(ofSize: 24)
            ]

            let size = text.size(withAttributes: attributes)
            context.translateBy(x: imageRect.width-size.height, y: (rect.height - size.width) / 2)
            context.rotate(by: CGFloat.pi / 2)

            text.draw(at: .zero, withAttributes: attributes)

            context.restoreGState()
        }
    }
}

更新:这就是我想要的结果enter image description here

swift macos swift4 nsimage
1个回答
1
投票

使用下面的翻译

demo

context.translateBy(x: self.bounds.maxX, y: (rect.height - size.width) / 2)

1
投票

希望你能明白CGContext变换的工作原理,如果不明白,就学习一下吧。

你的问题最简单的一个实现是这样的:文字是蓝色的矩形,你想画一个红色的矩形。

enter image description here

所以计算一个移位变换,然后旋转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 param是红色矩形的中心。

结果看起来像这样。enter image description here

请注意,我们用红色填满整个视图, 然后渲染图像,再渲染文本。没有过多的间距存在。如果有的话,我们会看到红色的线条。下面 的图像。

您可以下载演示 此处.

还有,请不要画 一切 一下 draw(_ rect: NSRect) 调用--至少尝试提取文本绘制func--它将使你在定义问题的变量时更加灵活。

更新:

我需要将文本 "翻转",使其底部指向中心,变换后的文本可以是这样的。

context.translateBy(x: textCenter.x-textSize.height/2, y: textCenter.y+textSize.width/2)
context.rotate(by: -CGFloat.pi / 2)

然后文字就会变成这个样子enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.