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
相关产品推荐
相关产品推荐

