如何实现基于图片的背景模糊效果?参考iBooks应用示例
实现类似iBooks的图片背景模糊效果
iBooks的背景模糊效果核心是模糊处理后的背景图+边缘渐变遮罩,下面给出两种贴合你思路的具体实现方案,适配iOS 14及以上:
方案一:UIVisualEffectView + 背景图(推荐)
这个方案直接利用系统原生模糊组件,还原度高且性能更优:
- 创建底层背景图视图
先添加UIImageView并设置aspectFill模式,确保图片铺满容器:
let backgroundImageView = UIImageView(image: yourBackgroundImage) backgroundImageView.contentMode = .scaleAspectFill backgroundImageView.clipsToBounds = true backgroundImageView.frame = view.bounds view.addSubview(backgroundImageView)
- 添加系统模糊层
使用UIBlurEffect创建模糊视图,iOS 14+可选择对应风格(iBooks常用.systemUltraThinMaterialDark或浅色等效风格):
let blurEffect = UIBlurEffect(style: .systemUltraThinMaterialDark) let blurView = UIVisualEffectView(effect: blurEffect) blurView.frame = view.bounds backgroundImageView.addSubview(blurView)
- 添加边缘渐变遮罩
为避免模糊背景与内容冲突,给上下边缘添加渐变暗化层:
// 顶部渐变遮罩 let topGradientLayer = CAGradientLayer() topGradientLayer.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: 120) topGradientLayer.colors = [UIColor.black.withAlphaComponent(0.3).cgColor, UIColor.clear.cgColor] topGradientLayer.startPoint = CGPoint(x: 0.5, y: 0) topGradientLayer.endPoint = CGPoint(x: 0.5, y: 1) blurView.layer.addSublayer(topGradientLayer) // 底部渐变遮罩 let bottomGradientLayer = CAGradientLayer() bottomGradientLayer.frame = CGRect(x: 0, y: view.bounds.height - 120, width: view.bounds.width, height: 120) bottomGradientLayer.colors = [UIColor.clear.cgColor, UIColor.black.withAlphaComponent(0.3).cgColor] bottomGradientLayer.startPoint = CGPoint(x: 0.5, y: 0) bottomGradientLayer.endPoint = CGPoint(x: 0.5, y: 1) blurView.layer.addSublayer(bottomGradientLayer)
方案二:提取图片平均色做渐变模糊
如果需要自定义模糊程度或规避系统模糊限制,可采用此思路:
- 提取图片区域平均色
编写工具方法获取图片顶部、底部区域的平均颜色:
func averageColor(in image: UIImage, rect: CGRect) -> UIColor? { guard let cgImage = image.cgImage, let context = CGContext(data: nil, width: Int(rect.width), height: Int(rect.height), bitsPerComponent: 8, bytesPerRow: Int(rect.width) * 4, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else { return nil } context.draw(cgImage, in: CGRect(x: -rect.origin.x, y: -rect.origin.y, width: image.size.width, height: image.size.height)) guard let data = context.data else { return nil } let pixels = data.bindMemory(to: UInt8.self, capacity: Int(rect.width * rect.height * 4)) var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0 let totalPixels = Int(rect.width * rect.height) for i in 0..<totalPixels { let offset = i * 4 r += CGFloat(pixels[offset]) g += CGFloat(pixels[offset+1]) b += CGFloat(pixels[offset+2]) } r /= CGFloat(totalPixels * 255) g /= CGFloat(totalPixels * 255) b /= CGFloat(totalPixels * 255) return UIColor(red: r, green: g, blue: b, alpha: 1.0) } // 获取顶部、底部区域平均色 let topRect = CGRect(x: 0, y: 0, width: yourBackgroundImage.size.width, height: yourBackgroundImage.size.height * 0.2) let bottomRect = CGRect(x: 0, y: yourBackgroundImage.size.height * 0.8, width: yourBackgroundImage.size.width, height: yourBackgroundImage.size.height * 0.2) let topColor = averageColor(in: yourBackgroundImage, rect: topRect) ?? .darkGray let bottomColor = averageColor(in: yourBackgroundImage, rect: bottomRect) ?? .black
- 创建自定义模糊渐变背景
先给原图添加高斯模糊,再叠加渐变层:
// 生成模糊图片 func blurredImage(from image: UIImage, radius: CGFloat = 20) -> UIImage? { let context = CIContext(options: [.useSoftwareRenderer: false]) guard let ciImage = CIImage(image: image) else { return nil } let filter = CIFilter(name: "CIGaussianBlur")! filter.setValue(ciImage, forKey: kCIInputImageKey) filter.setValue(radius, forKey: kCIInputRadiusKey) guard let outputImage = filter.outputImage else { return nil } return UIImage(ciImage: context.createCGImage(outputImage, from: ciImage.extent)!) } let blurredImage = blurredImage(from: yourBackgroundImage) let blurImageView = UIImageView(image: blurredImage) blurImageView.contentMode = .scaleAspectFill blurImageView.clipsToBounds = true blurImageView.frame = view.bounds view.addSubview(blurImageView) // 添加渐变层 let gradientLayer = CAGradientLayer() gradientLayer.frame = view.bounds gradientLayer.colors = [topColor.withAlphaComponent(0.4).cgColor, topColor.withAlphaComponent(0.1).cgColor, bottomColor.withAlphaComponent(0.1).cgColor, bottomColor.withAlphaComponent(0.4).cgColor] gradientLayer.locations = [0, 0.3, 0.7, 1] blurImageView.layer.addSublayer(gradientLayer)
注意事项
- 方案一的系统模糊会自动适配系统浅色/深色模式,若需固定风格,可选择
.dark或.light系列模糊样式。 - 方案二可通过调整
radius参数控制模糊程度,渐变的locations和透明度可根据需求微调。 - 确保背景图视图处于所有内容视图的最底层,避免遮挡交互元素。
内容的提问来源于stack exchange,提问作者Daulet Ashikbayev
相关产品推荐
相关产品推荐

