Swift/SwiftUI中径向模糊实现方案咨询:能否通过Radial Gradient与CIMaskedVariableBlur实现?
Absolutely! Using CIRadialGradient alongside CIMaskedVariableBlur is a great way to build a radial blur effect—where the center stays sharp and blur intensity increases (or decreases) outward. Let’s break down how to pull this off, plus cover a couple of alternative approaches that might fit your use case better.
Method 1: CIMaskedVariableBlur + CIRadialGradient
The core idea here is using a radial gradient as a mask to control the blur intensity across your image. CIMaskedVariableBlur uses the mask’s grayscale values: white areas get maximum blur, black areas stay sharp, and grays are intermediate.
Step-by-Step Implementation
- Create the radial gradient mask: Generate a gradient that transitions from black (sharp) at the center to white (blurry) at the edges (or vice versa, depending on your desired effect).
- Apply the masked blur: Feed your original image and the gradient mask into
CIMaskedVariableBlur. - Render the result in SwiftUI: Wrap the CoreImage filter chain in a
UIViewRepresentableor use SwiftUI’s built-inImagemodifier withcoreImageFilter.
Here’s a concrete SwiftUI example:
import SwiftUI import CoreImage import CoreImage.CIFilterBuiltins struct RadialBlurView: View { let originalImage: UIImage var body: some View { Image(uiImage: originalImage) .resizable() .scaledToFit() .coreImageFilter( "CIMaskedVariableBlur", parameters: [ kCIInputImageKey: originalImage.ciImage ?? CIImage(image: originalImage)!, kCIInputMaskImageKey: createRadialGradientMask(size: originalImage.size), kCIInputRadiusKey: 30.0 // Adjust blur intensity here ] ) } private func createRadialGradientMask(size: CGSize) -> CIImage { let gradientFilter = CIFilter.radialGradient() gradientFilter.center = CGPoint(x: size.width/2, y: size.height/2) gradientFilter.radius0 = 0 // Inner radius (sharp center) gradientFilter.radius1 = min(size.width, size.height)/2 // Outer radius (max blur) gradientFilter.color0 = CIColor.black // Sharp = black gradientFilter.color1 = CIColor.white // Blurry = white return gradientFilter.outputImage! } }
Note: If your UIImage doesn’t have a valid ciImage, fall back to converting it with CIImage(image: originalImage).
Method 2: CIGaussianBlur + Radial Gradient Blend
If you prefer a simpler approach (or need compatibility with older iOS versions), you can combine a full Gaussian blur with a radial gradient mask using blend modes:
- Apply a full
CIGaussianBlurto your image. - Overlay the original image with a radial gradient mask, using the
sourceInblend mode to only show the sharp center over the blurred background.
Example code snippet:
func radialBlurAlternative(image: UIImage, blurRadius: Double) -> UIImage? { guard let ciImage = CIImage(image: image) else { return nil } let size = image.size // Blur the entire image let blurFilter = CIFilter.gaussianBlur() blurFilter.inputImage = ciImage blurFilter.radius = blurRadius guard let blurredImage = blurFilter.outputImage else { return nil } // Create radial gradient mask let gradientFilter = CIFilter.radialGradient() gradientFilter.center = CGPoint(x: size.width/2, y: size.height/2) gradientFilter.radius0 = 0 gradientFilter.radius1 = min(size.width, size.height)/2 gradientFilter.color0 = CIColor.white // Keep original here gradientFilter.color1 = CIColor.black // Show blur here guard let mask = gradientFilter.outputImage else { return nil } // Combine original + blurred using the mask let compositeFilter = CIFilter.sourceInCompositing() compositeFilter.inputImage = ciImage compositeFilter.backgroundImage = blurredImage compositeFilter.maskImage = mask guard let outputCIImage = compositeFilter.outputImage else { return nil } let context = CIContext(options: nil) guard let outputCGImage = context.createCGImage(outputCIImage, from: outputCIImage.extent) else { return nil } return UIImage(cgImage: outputCGImage) }
Method 3: Using CIBokehBlur (iOS 15+)
If you’re targeting iOS 15 or later, CIBokehBlur can create a radial-like bokeh effect with customizable intensity and shape. While it’s not a pure radial blur, it’s great for creating aesthetic out-of-focus effects centered on a point:
Image(uiImage: originalImage) .resizable() .scaledToFit() .coreImageFilter( "CIBokehBlur", parameters: [ kCIInputImageKey: originalImage.ciImage ?? CIImage(image: originalImage)!, kCIInputRadiusKey: 20.0, kCIInputCenterKey: CIVector(x: originalImage.size.width/2, y: originalImage.size.height/2) ] )
Key Notes
- Adjust
radius0/radius1in the gradient to control how large the sharp center area is. - Tweak the
kCIInputRadiusKeyvalue to control the maximum blur intensity. - For performance, consider rendering the filtered image once (instead of applying the filter live) if it’s static.
内容的提问来源于stack exchange,提问作者Tahseen Rasheed

