计算点大小以适合矩形内的字符串

Calculate point size to fit string inside a rectangle

我正在创建一个将文本放在图像之上的东西。要绘制的文本的最大允许框架由我们的后端指定,我必须尽力适应用户在该矩形中输入的任何文本。

我查找了大量较早的答案,但所有答案似乎都使​​用 UILabel 自动拟合或只是暴力破解 String.boundingRect(with:options:attributes:context:)

我最初的想法是只使用文本矩形的高度作为磅值来划分,但这似乎不能 100% 起作用,而且不支持水平方向太长的文本。

这是我现在画东西的方式,只是为了了解一些上下文。

    let image = renderer.image { context in            
        backgroundImage.draw(at: .zero)

        let titleAttributes: [NSAttributedStringKey: Any] = [
            .font: UIFont(name: fontName, size: maxSize.height)!,
            .foregroundColor: UIColor.white,
            .paragraphStyle: NSMutableParagraphStyle(alignment: alignment),
            .shadow: NSShadow( color: .black, offset: .zero, radius: 28),
        ]

        (title as NSString).draw(with: maxFrame,
                                 options: .usesLineFragmentOrigin,
                                 attributes: titleAttributes,
                                 context: nil)
    }

有没有什么有效的方法可以在不使用 UILabel 或暴力破解的情况下找出适合矩形的字体磅值?

我又自己解决了!

我画的文字不允许断行,所以总是一行。在 Playgrounds 中使用强力方法时,我注意到文本宽度与字体大小成线性关系。所以这真的很容易。

extension UIFont {
    convenience init?(named fontName: String, fitting text: String, into targetSize: CGSize, with attributes: [NSAttributedStringKey: Any], options: NSStringDrawingOptions) {
        var attributes = attributes
        let fontSize = targetSize.height

        attributes[.font] = UIFont(name: fontName, size: fontSize)
        let size = text.boundingRect(with: CGSize(width: .greatestFiniteMagnitude, height: fontSize),
                                     options: options,
                                     attributes: attributes,
                                     context: nil).size

        let heightSize = targetSize.height / (size.height / fontSize)
        let widthSize = targetSize.width / (size.width / fontSize)

        self.init(name: fontName, size: min(heightSize, widthSize))
    }
}

此扩展程序将启动一种字体,保证适合目标矩形内只要它是 1 行。