在NSImage的右侧绘制文本-不需要的间距 [英] Drawing Text on Right Side of NSImage - Unwanted Spacing

查看:255
本文介绍了在NSImage的右侧绘制文本-不需要的间距的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下代码在图像的右侧绘制文本

I'm using the following code to draw text on the right side on an image

         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()

如您所见,右侧有一些多余的间距.我该如何解决?

As you can see there is some excessive spacing from the right side.How can i fix it?

更新:

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()
        }
    }
}

更新: 这是理想的结果

Update: This is the desired result

推荐答案

我希望您了解CGContext转换是如何工作的,如果没有,请学习它.

I hope you understand how CGContext transforms work, if not, learn it.

问题的最简单实现之一是这样的:文本是蓝色矩形,您想绘制一个红色矩形.

One of the simplest implementations of your problem is like this: the text is blue rectangle, you want to draw a red rectangle.

所以足够计算一个位移变换,然后旋转90. 在这种情况下,移位变换是蓝色矩形的左下方,同时红色矩形的右下方.

So it's enough to calculate a shift transform, then rotate-90. A shift transform in this case is a left-bottom of the blue rectangle, and at the same time the right-bottom of the red rectangle.

您的DemoView可能看起来像这样:

Your DemoView can look like this:

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参数是红色矩形的中心.

In this code, the centerInView param is the center of your red rectangle.

结果看起来像这样:

The result looks like this:

请注意,我们用红色填充整个视图,然后渲染图像,然后渲染文本. 没有过多的间距.如果存在,我们将在图像的下方看到红线.

Please note that we fill the entire view with red color, then we render the image, then we render the text. No excessive spacing is present. If it was present, we would see red lines below the image.

您可以在此处下载演示.

也请不要在一个draw(_ rect: NSRect)调用中绘制所有内容-尝试至少提取文本绘制功能-这将为您提供更多的灵活性来定义问题的变量

And please don't draw everything in a one draw(_ rect: NSRect) call - try to extract at least the text drawing func - it'll give you much more flexibility in defining the variables of the problem.

更新:

我需要将文本翻转",因此其底边指向中心,变换看起来像这样:

I you need the text to be "flipped", so its bottom side points toward the center, the transform can look like this:

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

,文本将如下所示:

and the text will look like this:

这篇关于在NSImage的右侧绘制文本-不需要的间距的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆