【问题标题】:How to draw String in CGContext?如何在 CGContext 中绘制字符串?
【发布时间】:2018-10-18 11:58:44
【问题描述】:

我正在尝试在 CALayer 的覆盖 draw 方法中绘制一个字符串(我正在为 iOS 编程)。

override func draw(in ctx: CGContext) {
    let font = UIFont.systemFont(ofSize: 30)
    let string = NSAttributedString(string: "23", attributes: [NSAttributedStringKey.font: font])
    string.draw(at: CGPoint(x: 200, y: 200))
}

然而,这并没有绘制任何东西(至少没有任何东西是可见的)。更改填充和描边颜色没有任何区别。

如果我画一条线,它会显示出来,所以这个函数被调用了。我知道有一个CATextLayer,但我需要直接绘制字符串。在 Swift 4 时代,你应该如何在CGContext 中画一个字符串?再多的网络搜索都没有得到答案。

【问题讨论】:

  • 我现在无法测试它,但我知道在draw(ctx:) 上不调用super 可能会是problematic
  • CALayer 文档说:“此方法的默认实现本身不进行任何绘图。”只是为了确保我使用超级调用尝试了代码:没有区别。
  • 对不起,我不知道为什么我将您的问题与 UIView drawRect 相关联,我的错。

标签: ios swift calayer cgcontext


【解决方案1】:

我假设您知道所有其他设置。这里的关键是您没有将 CGContext 设为当前的。只需添加两行代码即可解决问题。希望你能得到答案。

   override func draw(in ctx: CGContext) {
   UIGraphicsPushContext(ctx)
    let font = UIFont.systemFont(ofSize: 30)
    let string = NSAttributedString(string: "23", attributes: [NSAttributedString.Key.font: font])
    string.draw(at: CGPoint(x: 200, y: 200))
   UIGraphicsPopContext()
}

【讨论】:

  • 这解决了它。非常感谢! CGContext 有各种绘图方法,但没有做基本的文本绘图,我觉得很困惑。
【解决方案2】:

如果视图被聚焦,上述答案有效。

很遗憾,它不能在屏幕外位图或 CALayer 上下文中工作。

在任何 CGContext 中绘制字符串的正确且通用的方法是使用 CoreText api。它可以在所有 Apple 平台上运行,并且具有强大的功能。

https://developer.apple.com/documentation/coretext

例子:

import Foundation
import Quartz

/// LazyFoxLayer
///
/// Will draw the "The lazy fox…" string in the bottom right corner of the layer,
/// with a margin of 10 pixels.

class LazyFoxLayer: CALayer {

    func draw(ctx: CGContext) {
        ctx.saveGState()
    
        // Parameters

        let margin: CGFloat = 10
        let color = CGColor.black
        let fontSize: CGFloat = 32
        // You can use the Font Book app to find the name
        let fontName = "Chalkboard" as CFString 
        let font = CTFontCreateWithName(fontName, fontSize, nil)

        let attributes: [NSAttributedString.Key : Any] = [.font: font, .foregroundColor: color]

        // Text

        let string = "The lazy fox…"
        let attributedString = NSAttributedString(string: string, 
                                                  attributes: attributes)

        // Render

        let line = CTLineCreateWithAttributedString(attributedString)
        let stringRect = CTLineGetImageBounds(line, ctx)

        ctx.textPosition = CGPoint(x: bounds.maxX - stringRect.width - margin, 
                                   y: bounds.minY + margin)

        CTLineDraw(line, ctx)

        ctx.restoreGState()
    }
}

干杯:)

【讨论】:

  • 这很好用。谢谢!我们遇到的一个问题是文本有点模糊。我们可以做些什么来提高绘图分辨率或更好地达到像素边界?
  • 不确定..可能使用标准文本大小 (9, 11, 13) 并可能在标准化值 (round(x), round(y)) 上对齐文本位置。检查 CGContext.allowsAntialiasing 是否设置为 true。
  • 原来“layer.contentsScale = 2”修复了模糊渲染。再次感谢 Moose。这是我们能找到的唯一直接在图层上工作的方法!
  • FWIW,在最近的 Swift 版本中,你需要这样的东西:let attributes: [NSAttributedString.Key : Any]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多