在图像右上角绘制文本

Posted

技术标签:

【中文标题】在图像右上角绘制文本【英文标题】:Draw text in image right corner 【发布时间】:2017-06-01 11:55:25 【问题描述】:

我想在 UIImage 的右上角或右下角绘制文本。 我有一个扩展,可以很好地绘制文本,但问题是将文本定位在屏幕的右侧(因为文本被剪切)。

这是扩展名:

extension UIImage 

func addText(drawText: NSString, atPoint: CGPoint, textColor: UIColor?, textFont: UIFont?) -> UIImage

    // Setup the font specific variables
    var _textColor: UIColor
    if textColor == nil 
        _textColor = UIColor.white
     else 
        _textColor = textColor!
    

    var _textFont: UIFont
    if textFont == nil 
        _textFont = UIFont.systemFont(ofSize: 50)
     else 
        _textFont = textFont!
    

    // Setup the image context using the passed image
    UIGraphicsBeginImageContext(size)

    // Setup the font attributes that will be later used to dictate how the text should be drawn
    let textFontAttributes = [
        NSFontAttributeName: _textFont,
        NSForegroundColorAttributeName: _textColor,
        ] as [String : Any]

    // Put the image into a rectangle as large as the original image
    draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))

    // Create a point within the space that is as bit as the image
    let rect = CGRect(x: atPoint.x, y: atPoint.y, width: size.width, height: size.height)


    // Draw the text into an image
    drawText.draw(in: rect, withAttributes: textFontAttributes)

    // Create a new image out of the images we have created
    let newImage = UIGraphicsGetImageFromCurrentImageContext()

    // End the context now that we have the image we need
    UIGraphicsEndImageContext()

    //Pass the image back up to the caller
    return newImage!


问题是如果文本太长或太大,它会超出屏幕。我需要更改原点以将文本从右向左写入,这样它只会在左侧占用空间,而不是在屏幕右侧占用空间。我怎么能这样做?

【问题讨论】:

添加标签作为子视图并创建图像视图的“截图”可能更容易。 Here is how. 【参考方案1】:

有一个简单的函数调用来获取字符串的“边界框”。您可以使用它来定位应将文本绘制到图像中的位置:

    // get the bounding-box for the string
    let stringSize = drawText.size(attributes: textFontAttributes)

    // position the bounding-box at the bottom-right corner of the image
    let x = self.size.width - ceil(stringSize.width)
    let y = self.size.height - ceil(stringSize.height)

    let rect = CGRect(x: x, y: y, width: stringSize.width, height: stringSize.height)

    // Draw the text into an image
    drawText.draw(in: rect, withAttributes: textFontAttributes)

请注意,此示例代码将文本定位在右下角 - 忽略 atPoint 参数。您可能会将其更改为 whichCorner 类型参数,然后适当地计算 xy 位置。

顺便说一句...drawText 是一个可怕的变量名称——它听起来像一个函数。使用textToDraw 之类的内容更具可读性。


这是一个修改后的函数,使用了atCorner 参数,其中的值是:

        +-----------+ 
        | 0       1 | 
        |           | 
        |           | 
        | 3       2 |
        +-----------+

编辑:使用右对齐的段落样式(由 Thilina Chamin Hewagama 建议)有一些优势。这个编辑后的版本甚至可以处理带有"\n" 嵌入换行符的文本。

extension UIImage 

    func addText(textToDraw: NSString, atCorner: Int, textColor: UIColor?, textFont: UIFont?) -> UIImage 

        // Setup the font specific variables
        var _textColor: UIColor
        if textColor == nil 
            _textColor = UIColor.white
         else 
            _textColor = textColor!
        

        var _textFont: UIFont
        if textFont == nil 
            _textFont = UIFont.systemFont(ofSize: 50)
         else 
            _textFont = textFont!
        

        // Setup the image context using the passed image
        UIGraphicsBeginImageContext(size)

        // Put the image into a rectangle as large as the original image
        draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))

        let titleParagraphStyle = NSMutableParagraphStyle()

        // Setup the font attributes that will be later used to dictate how the text should be drawn
        let textFontAttributes = [
            NSFontAttributeName: _textFont,
            NSForegroundColorAttributeName: _textColor,
            NSParagraphStyleAttributeName: titleParagraphStyle
            ] as [String : Any]

        // get the bounding-box for the string
        var stringSize = textToDraw.size(attributes: textFontAttributes)

        // draw in rect functions like whole numbers
        stringSize.width = ceil(stringSize.width)
        stringSize.height = ceil(stringSize.height)

        var rect = CGRect(origin: CGPoint.zero, size: self.size)

        switch atCorner 

        case 1:
            // top-right
            titleParagraphStyle.alignment = .right

        case 2:
            // bottom-right
            rect.origin.y = self.size.height - stringSize.height
            titleParagraphStyle.alignment = .right

        case 3:
            // bottom-left
            rect.origin.y = self.size.height - stringSize.height

        default:
            // top-left
            // don't need to change anything here
            break

        

        // Draw the text into an image
        textToDraw.draw(in: rect, withAttributes: textFontAttributes)

        // Create a new image out of the images we have created
        let newImage = UIGraphicsGetImageFromCurrentImageContext()

        // End the context now that we have the image we need
        UIGraphicsEndImageContext()

        //Pass the image back up to the caller
        return newImage!
    


【讨论】:

感谢“边界框”功能,这就是我搜索的内容。问题解决了! 您好,我尝试了您的解决方案,文本大小位于正确的位置 - 这非常棒。但是文本字体大小会根据图像的大小而变化。我也许可以将图像缩放到特定大小并绘制文本可能会解决问题,但图像质量不会相同......任何建议将不胜感激。 @kamyFC - 不太确定你在问什么...... “文本字体大小因图像大小而异” --- 你在创建和传递字体?还是只使用“默认”?

以上是关于在图像右上角绘制文本的主要内容,如果未能解决你的问题,请参考以下文章

黑莓中的自定义文本框

将旋转的图像转换为矩形左上角

向使用 GDI+ 绘制的图像添加文本

HTML5 Canvas:图像上的文本绘制在图像更改时停止显示

在画布中间绘制图像

从绘制在图像上的文本中删除顶部和底部填充