引言
在实际的项目开发中,我们经常会遇到一些看似简单,但在实现时却充满挑战的需求。比如在开发付费通话功能时,我们需要展示最近通话的用户记录,其中包括用户的头像和昵称。为了保护用户隐私并且提升界面的美观性,我们希望对这些信息进行模糊处理。
头像的模糊处理是比较容易实现的,iOS 系统提供了丰富的图像处理工具。但当我们尝试对文本进行模糊处理时,问题就变得不那么简单了。文字的高斯模糊效果并不像图片那样直接应用已有的 API,想要达到类似的效果需要一些技巧。
本篇博客将介绍如何通过定义UILabel,实现对文字内容的高斯模糊效果,解决这一难题。
实现思路
要实现文字的高斯模糊效果,我们可以借鉴实现图片高斯模糊的思路。在处理图片模糊时,通常有两种常见的方案:
- 使用系统的UIBlurEffect 高斯模糊图层:这是最简单的方法,我们可以直接使用系统提供的 UIBlurEffect,将其作为一个覆盖层叠加在图片上。这种方法非常适合静态图像的模糊处理,系统会自动为我们处理模糊效果,简单且高效。
- 使用CIFilter 进行图像处理:另一种方法是利用Core Image 的 CIFilter,通过为图片应用高斯模糊滤镜来实现。这种方法允许我们对模糊的强度和效果进行更多的控制,也能处理动态变化的图像。
对于文字的高斯模糊效果,我们可以借用类似的思路。我们将通过自定义UILabel,在绘制文本时对其进行处理,通过借助Core Graphics和CIFilter等工具,在渲染文本时手动实现。首先将文字内容绘制成一个图片,然后再为图片添加滤镜效果,最后再将图片绘制到自定义UILabel中显示。
代码实现
代码实现我们可以分为三个部分:
- 首先是通过Core Graphics将文本绘制为图片。
- 然后是利用CIFilter为图片添加高斯模糊滤镜。
- 将高斯模糊后的图片绘制到自定的UILabel中。
我们创建一个PHBlurLabel集成自UILabel,然后重写它的draw(_ rect:CGRect)方法来一步步实现这一效果。
使用Core Graphics将文本绘制为图片
借助Core Graphics将文本内容根据文本的设置属性生成一张文本图片,具体代码如下:
class PHBlurLabel: UILabel {
override func draw(_ rect: CGRect) {
if rect.isEmpty {
return
}
guard let text = self.text else {
return
}
// 1.获取当前上下文
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
guard UIGraphicsGetCurrentContext() != nil else {
return
}
// 2.设置文本属性
var attributes: [NSAttributedString.Key : Any] = [:]
attributes[NSAttributedString.Key.font] = self.font
attributes[NSAttributedString.Key.foregroundColor] = self.textColor
// 3.绘制文本
text.draw(in: rect, withAttributes: attributes)
// 4.获取图片
guard let textImage = UIGraphicsGetImageFromCurrentImageContext() else {
return
}
UIGraphicsEndImageContext()
....
}
....
}
- 我们只需要在文本有数据时再绘制,因此先加了两组判断。
- 获取绘图的上下文。
- 设置文本属性,开始绘制文本。
- 获取绘制好的图片,关闭绘图上下文。
使用CIFilter为图片添加高斯模糊滤镜
借助CIFilter的强大功能为图片添加CIGaussianBlur高斯模糊滤镜,并输出新的图片,具体代码如下:
// 5.绘制模糊效果
guard let ciImage = CIImage(image: textImage) else {
return
}
let filter = CIFilter(name: "CIGaussianBlur")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(10.0, forKey: kCIInputRadiusKey)
guard let outputImage = filter?.outputImage else {
return
}
- 将UIImage转换为CIIMage。
- 选择合适滤镜。
- 设置图片的模糊程度。
- 获取滤镜后的图片。
重新绘制图片
接下来我们需要将已经获取的模糊图片再重新绘制到自定义的UILabel上,这时候需要注意Core Graphics的坐标系与我们通常所使用frame是相反的,因此我们需要做一点处理来使图片正常显示而不是颠倒的图片。
// 6.绘制图片
guard let contextRef = UIGraphicsGetCurrentContext() else {
return
}
guard let cgImage = CIContext().createCGImage(outputImage, from: ciImage.extent) else {
return
}
// 保存当前上下文状态
contextRef.saveGState()
// 翻转上下文坐标系,使其与图像坐标系对齐
contextRef.translateBy(x: 0, y: rect.size.height) // 平移
contextRef.scaleBy(x: 1.0, y: -1.0) // 翻转y轴
// 在修正后的坐标系中绘制图片
contextRef.draw(cgImage, in: rect)
// 恢复上下文状态
contextRef.restoreGState()
模糊文字UILabel使用
在使用时我们只需要想普通的UILabel一样进行创建,设置和添加即可。
let blurLabel = PHBlurLabel()
blurLabel.font = UIFont.systemFont(ofSize: 20)
blurLabel.text = "Hello World"
blurLabel.textColor = .black
view.addSubview(blurLabel)
blurLabel.snp.makeConstraints { make in
make.top.equalTo(300)
make.centerX.equalToSuperview()
}
效果如下:
这是模糊程度为10的效果,可以根据需要调整数值。但是我们看见仍然有一个小瑕疵,文字的左右分界线过于明显,这通常不会被设计同学接受。
效果优化
由于文字被高斯模糊之后,不可避免的需要向四周扩散一些像素,这导致在UILabel的边缘会出现非常明显的接线。为了解决这一问题,我们不得不让UILabel的实际宽度比内容宽度稍微大上一些,也就是说在文字与组件之间有一些内边距。
为了实现这个效果我们可以通过重写UIlabel的intrinsicContentSize属性,具体代码如下:
var textInsets = UIEdgeInsets(top: 0, left: 4, bottom: 0, right: 4)
override var intrinsicContentSize: CGSize {
let size = super.intrinsicContentSize
return CGSize(width: size.width + textInsets.left + textInsets.right,
height: size.height + textInsets.top + textInsets.bottom)
}
并在绘制时调整它的rect:
// 2.设置文本属性
var attributes: [NSAttributedString.Key : Any] = [:]
attributes[NSAttributedString.Key.font] = self.font
attributes[NSAttributedString.Key.foregroundColor] = self.textColor
let rect = CGRect(x: 0 + 4.0, y: 0, width: rect.size.width - 8.0, height: rect.size.height)
// 3.绘制文本
text.draw(in: rect, withAttributes: attributes)
最终效果如下:
结语
通过本文的介绍,我们成功地实现了一个自定义的高斯模糊 UILabel
,并展示了如何通过继承 UILabel
类来绘制带有模糊效果的文字。虽然系统默认的文本渲染并不直接支持模糊效果,但通过灵活运用 Core Graphics 和 Core Image 的滤镜,我们可以非常方便地对文本进行自定义处理,从而实现类似高斯模糊的视觉效果。
值得注意的是,虽然这种方法能够为我们带来很好的效果,但在实际应用中我们也要关注性能。高斯模糊可能会对渲染性能产生一定影响,尤其是在动态文本或高频率更新的场景中,因此我们需要根据实际需求进行优化。
总的来说,文本的高斯模糊处理虽然在 iOS 开发中并不常见,但通过一些巧妙的技巧,我们可以在不同的应用场景中灵活运用,为用户带来更丰富、更美观的界面体验。
希望本文能为你在 iOS 开发中解决类似问题提供一些帮助,如果你有更多的优化思路或实践经验,欢迎分享。
源码地址:
https://github.com/Louis1239/PHBlurLabel.githttps://github.com/Louis1239/PHBlurLabel.githttps://mp.csdn.net/mp_download/manage/download/UpDetailedhttps://mp.csdn.net/mp_download/manage/download/UpDetailed