You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中消除文本转图片渲染后边缘黑线的解决方法

CoreGraphics渲染带属性文本图片的黑线/黑块问题解决

问题原因

  • 边缘黑线:size(withAttributes:)返回的文本尺寸常包含小数像素,亚像素渲染时会产生模糊边缘;且原代码仅设置背景色但未实际填充整个画布,不透明上下文默认黑色背景,未被覆盖的边缘像素显示为黑线。
  • 多行空白黑块:未提前填充完整背景,文本绘制区域外的画布保留默认黑色,多行文本尺寸计算不准确时,空白区域无法被背景色覆盖。

解决代码及说明

func textualImage(text: String, textSize: CGFloat, textColor: UIColor, backgroundColor: UIColor = .white) -> UIImage? {
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.alignment = .center
    
    let attributes: [NSAttributedString.Key: Any] = [
        .foregroundColor: textColor,
        .font: UIFont.systemFont(ofSize: textSize),
        .paragraphStyle: paragraphStyle
    ]
    
    // 用更精确的方法计算多行文本尺寸,向上取整到整数像素避免亚像素问题
    let maxSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
    let textRect = text.boundingRect(with: maxSize, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: attributes, context: nil)
    let renderSize = CGSize(width: ceil(textRect.width), height: ceil(textRect.height))
    
    // 使用iOS 10+推荐的UIGraphicsImageRenderer,替代旧的上下文API
    let renderer = UIGraphicsImageRenderer(size: renderSize)
    return renderer.image { context in
        // 先填充整个画布背景,确保无遗漏区域
        backgroundColor.setFill()
        context.fill(CGRect(origin: .zero, size: renderSize))
        
        // 绘制文本
        text.draw(in: CGRect(origin: .zero, size: renderSize), withAttributes: attributes)
    }
}

关键修改点

  • 背景填充修正:明确调用context.fill()填充整个画布,彻底覆盖默认黑色背景,解决空白区域变黑问题。
  • 像素对齐处理:将文本尺寸向上取整为整数像素,消除亚像素渲染导致的边缘黑线。
  • 精确尺寸计算:改用boundingRect(with:options:attributes:context:)计算文本尺寸,开启.usesLineFragmentOrigin和.usesFontLeading选项,适配多行文本的准确行高与换行逻辑。
  • API升级:使用UIGraphicsImageRenderer替代旧的上下文创建方式,API更稳定,自动处理上下文生命周期,减少渲染异常。

内容的提问来源于stack exchange,提问作者Charles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 07:43:21