未命名.png
extension UIView{
/// 将视图内容生成模糊图像,并返回一个模糊覆盖图层(UIImageView)
/// - Parameters:
/// - blurRadius: 模糊半径,值越大越模糊(推荐 30~50)
/// - completion: 模糊图像生成后的回调,返回 UIImageView(模糊层)
@objc func makeTextAppearAsBlackBlob(blurRadius: CGFloat = 10.0,
completion: @escaping (_ blurredImage: UIImageView?) -> Void) {
// 1. 在主线程中渲染视图内容为图片(必须主线程才能确保文字等内容完整绘制)
DispatchQueue.main.async {[weak self] in
guard let self = self else { return }
// 创建图像渲染器,大小为视图尺寸
let renderer = UIGraphicsImageRenderer(size: self.bounds.size)
// 渲染 view 当前内容为 UIImage(截图)
let snapshot = renderer.image { _ in
self.drawHierarchy(in: self.bounds, afterScreenUpdates: true)
}
// 2. 在后台线程处理图像模糊,避免阻塞 UI
DispatchQueue.global(qos: .userInitiated).async {
// 转换为 CIImage 用于滤镜处理
guard let ciImage = CIImage(image: snapshot),
let blurFilter = CIFilter(name: "CIGaussianBlur") else {
DispatchQueue.main.async { completion(nil) }
return
}
// 设置滤镜输入图像和模糊半径
blurFilter.setValue(ciImage, forKey: kCIInputImageKey)
blurFilter.setValue(blurRadius, forKey: kCIInputRadiusKey)
// 获取滤镜输出图像(模糊后的图)
guard let outputImage = blurFilter.outputImage else {
DispatchQueue.main.async { completion(nil) }
return
}
// 修正输出图像区域,避免高斯模糊造成边缘裁剪(扩大区域)
let cropRect = ciImage.extent.insetBy(dx: -blurRadius, dy: -blurRadius)
// 使用 CIContext 将输出图像转为 CGImage
let context = CIContext()
guard let cgImage = context.createCGImage(outputImage, from: cropRect) else {
DispatchQueue.main.async { completion(nil) }
return
}
// 回到主线程返回模糊视图
DispatchQueue.main.async {
// 转换为 UIImage 后创建 UIImageView(作为模糊覆盖层)
let blurredImage = UIImage(cgImage: cgImage)
let imageView = UIImageView(image: blurredImage)
imageView.frame = self.bounds
completion(imageView)
}
}
}
}
}
使用示例
textView.makeTextAppearAsBlackBlob { [weak self] blurredImage in
guard let self = self else { return }
guard let blurredImage else{ return }
textView.addSubview(blurredImage)
}
Label的扩展
extension UILabel {
/// 为 UILabel 添加模糊遮罩图像,返回模糊图层 UIImageView
/// - Parameters:
/// - blurRadius: 模糊半径(数值越大越模糊),默认 10
/// - completion: 生成模糊图后的回调,返回 UIImageView(已设置好 frame)
override func makeTextAppearAsBlackBlob(blurRadius: CGFloat = 10.0,
completion: @escaping (UIImageView?) -> Void) {
// 设置文本颜色为黑色,确保模糊后更像“黑团”
self.textColor = .cBlack
// 异步到主线程
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
// 使用 UIGraphicsImageRenderer 截图 UILabel 内容(包括文字)
let renderer = UIGraphicsImageRenderer(size: self.bounds.size)
let image = renderer.image { _ in
// drawText 是 UILabel 的绘图方法,可以准确绘制 label 的文字
self.drawText(in: self.bounds)
}
// 模糊处理放在后台线程
DispatchQueue.global(qos: .userInitiated).async {
let context = CIContext(options: nil)
// 转换为 CIImage 用于滤镜处理
guard let ciImage = CIImage(image: image),
let blurFilter = CIFilter(name: "CIGaussianBlur") else {
DispatchQueue.main.async { completion(nil) }
return
}
// 设置输入图像和模糊半径
blurFilter.setValue(ciImage, forKey: kCIInputImageKey)
blurFilter.setValue(blurRadius, forKey: kCIInputRadiusKey)
// 获取模糊输出图像
guard let output = blurFilter.outputImage else {
DispatchQueue.main.async { completion(nil) }
return
}
// ⚠️ 默认输出图像可能被裁剪,需扩大模糊区域
let cropRect = ciImage.extent.insetBy(dx: -blurRadius, dy: -blurRadius)
// 生成 CGImage 图像
guard let cgImage = context.createCGImage(output, from: cropRect) else {
DispatchQueue.main.async { completion(nil) }
return
}
// 返回主线程回调 UIImageView
DispatchQueue.main.async {
let blurredImage = UIImage(cgImage: cgImage)
let imageView = UIImageView(image: blurredImage)
imageView.frame = self.bounds
completion(imageView)
}
}
}
}
}
使用示例
label.makeTextAppearAsBlackBlob(blurRadius: 10) { blurredImage in
guard let blurredImage else {
return
}
label.superview?.addSubview(blurredImage)
label.isHidden = true
}
仅供参考