实现 iOS 自定义高斯模糊文字效果的 UILabel(文末有Demo)

引言

在实际的项目开发中,我们经常会遇到一些看似简单,但在实现时却充满挑战的需求。比如在开发付费通话功能时,我们需要展示最近通话的用户记录,其中包括用户的头像和昵称。为了保护用户隐私并且提升界面的美观性,我们希望对这些信息进行模糊处理。

头像的模糊处理是比较容易实现的,iOS 系统提供了丰富的图像处理工具。但当我们尝试对文本进行模糊处理时,问题就变得不那么简单了。文字的高斯模糊效果并不像图片那样直接应用已有的 API,想要达到类似的效果需要一些技巧。

本篇博客将介绍如何通过定义UILabel,实现对文字内容的高斯模糊效果,解决这一难题。

实现思路

要实现文字的高斯模糊效果,我们可以借鉴实现图片高斯模糊的思路。在处理图片模糊时,通常有两种常见的方案:

  1. 使用系统的UIBlurEffect 高斯模糊图层:这是最简单的方法,我们可以直接使用系统提供的 UIBlurEffect,将其作为一个覆盖层叠加在图片上。这种方法非常适合静态图像的模糊处理,系统会自动为我们处理模糊效果,简单且高效。
  2. 使用CIFilter 进行图像处理:另一种方法是利用Core Image 的 CIFilter,通过为图片应用高斯模糊滤镜来实现。这种方法允许我们对模糊的强度和效果进行更多的控制,也能处理动态变化的图像。

对于文字的高斯模糊效果,我们可以借用类似的思路。我们将通过自定义UILabel,在绘制文本时对其进行处理,通过借助Core Graphics和CIFilter等工具,在渲染文本时手动实现。首先将文字内容绘制成一个图片,然后再为图片添加滤镜效果,最后再将图片绘制到自定义UILabel中显示。

代码实现

代码实现我们可以分为三个部分:

  1. 首先是通过Core Graphics将文本绘制为图片。
  2. 然后是利用CIFilter为图片添加高斯模糊滤镜。
  3. 将高斯模糊后的图片绘制到自定的UILabel中。

我们创建一个PHBlurLabel集成自UILabel,然后重写它的draw(_ rect:CGRect)方法来一步步实现这一效果。

使用Core Graphics将文本绘制为图片

借助Core Graphics将文本内容根据文本的设置属性生成一张文本图片,具体代码如下:

Swift 复制代码
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()
        ....
    }
    ....
}
  1. 我们只需要在文本有数据时再绘制,因此先加了两组判断。
  2. 获取绘图的上下文。
  3. 设置文本属性,开始绘制文本。
  4. 获取绘制好的图片,关闭绘图上下文。

使用CIFilter为图片添加高斯模糊滤镜

借助CIFilter的强大功能为图片添加CIGaussianBlur高斯模糊滤镜,并输出新的图片,具体代码如下:

Swift 复制代码
        // 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
        }
  1. 将UIImage转换为CIIMage。
  2. 选择合适滤镜。
  3. 设置图片的模糊程度。
  4. 获取滤镜后的图片。

重新绘制图片

接下来我们需要将已经获取的模糊图片再重新绘制到自定义的UILabel上,这时候需要注意Core Graphics的坐标系与我们通常所使用frame是相反的,因此我们需要做一点处理来使图片正常显示而不是颠倒的图片。

Swift 复制代码
        // 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一样进行创建,设置和添加即可。

Swift 复制代码
        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属性,具体代码如下:

Swift 复制代码
    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:

Swift 复制代码
        // 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

相关推荐
库奇噜啦呼1 天前
【iOS】static、const、extern关键字
ios
zzywxc7871 天前
AI工具全景洞察:从智能编码到模型训练的全链路剖析
人工智能·spring·ios·prompt·ai编程
前端 贾公子1 天前
《Vuejs设计与实现》第 16 章(解析器) 上
vue.js·flutter·ios
Digitally1 天前
如何将大型音频文件从 iPhone 发送到不同的设备
ios·iphone
吴Wu涛涛涛涛涛Tao2 天前
Flutter 实现「可拖拽评论面板 + 回复输入框 + @高亮」的完整方案
android·flutter·ios
搜狐技术产品小编20232 天前
CAEmitterLayer:iOS 中创建炫酷粒子效果的魔法工具
macos·ios·objective-c·cocoa
00后程序员张3 天前
iOS App 混淆与资源保护:iOS配置文件加密、ipa文件安全、代码与多媒体资源防护全流程指南
android·安全·ios·小程序·uni-app·cocoa·iphone
咕噜签名分发冰淇淋3 天前
内测分发是什么?
ios
2501_916007473 天前
Transporter App 使用全流程详解:iOS 应用 ipa 上传工具、 uni-app 应用发布指南
android·ios·小程序·https·uni-app·iphone·webview