Skip to content

Instantly share code, notes, and snippets.

@juliensagot
Last active November 11, 2024 04:13
Show Gist options
  • Save juliensagot/9cbda1d00312814218c4d3563f44e0fb to your computer and use it in GitHub Desktop.
Save juliensagot/9cbda1d00312814218c4d3563f44e0fb to your computer and use it in GitHub Desktop.
SwiftUI variable blur view
import Foundation
import SwiftUI
import UIKit
extension UIBlurEffect {
public static func variableBlurEffect(radius: Double, imageMask: UIImage) -> UIBlurEffect? {
let methodType = (@convention(c) (AnyClass, Selector, Double, UIImage) -> UIBlurEffect).self
let selectorName = ["imageMask:", "effectWithVariableBlurRadius:"].reversed().joined()
let selector = NSSelectorFromString(selectorName)
guard UIBlurEffect.responds(to: selector) else { return nil }
let implementation = UIBlurEffect.method(for: selector)
let method = unsafeBitCast(implementation, to: methodType)
return method(UIBlurEffect.self, selector, radius, imageMask)
}
}
struct VariableBlurView: UIViewRepresentable {
let radius: Double
let mask: Image
func makeUIView(context: Context) -> UIVisualEffectView {
let maskImage = ImageRenderer(content: mask).uiImage
let effect = maskImage.flatMap {
UIBlurEffect.variableBlurEffect(radius: radius, imageMask: $0)
}
return UIVisualEffectView(effect: effect)
}
func updateUIView(_ view: UIVisualEffectView, context: Context) {
let maskImage = ImageRenderer(content: mask).uiImage
view.effect = maskImage.flatMap {
UIBlurEffect.variableBlurEffect(radius: radius, imageMask: $0)
}
}
}
#Preview {
VStack(spacing: 0) {
Circle()
.foregroundStyle(.red)
Circle()
.foregroundStyle(.green)
Circle()
.foregroundStyle(.blue)
}
.frame(maxWidth: .infinity, alignment: .center)
.overlay(
VariableBlurView(radius: 10, mask: Image(.gradient))
.ignoresSafeArea()
)
}
@juliensagot
Copy link
Author

This is how it looks with a simple black(alpha: 0) to black(alpha: 1) gradient:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment