如何制作精确模糊效果

4

这是一个图片描述 我想要模糊后的效果像第一张图片那样。

这是一个图片描述

我已经写了一些代码,使它看起来像第二张图片。

我的模糊代码如下

    let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.Dark)
    blurEffectView = UIVisualEffectView(effect: blurEffect)
    blurEffectView.layer.opacity = 0.8
    blurEffectView.alpha = 0.6
    blurEffectView.frame = CGRectMake(0, 42, UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height - 42)
    sourceView.addSubview(blurEffectView)

Sourceview 是我的背景视图。我想要让它模糊。有什么建议吗?


@Lalit Kumar,首先我尝试了没有透明度和alpha的效果,但是看不到背景视图。然后我进行了修改。还尝试了额外的轻和浅模糊效果。 - Jecky
我认为你没有做错任何事情,除了设置模糊效果视图的框架。你应该使用 blueEffectView.frame = sourceView.frame。另外尝试使用活力效果。 - Kumar
@Lalit Kumar,框架对我来说很完美,但第一张图片中的文本也会变得模糊。在我的代码中,文本没有模糊。 - Jecky
可能是由于您添加模糊效果视图的方式或调用代码的位置/时间。你可以添加一些更相关的代码吗? - Kumar
好的。但是你是在哪个方法中添加这段代码的?这段代码是在什么时候被调用的?你是在用户点击左上角还是在viewDidLoad中添加这段代码的? - Kumar
显示剩余2条评论
1个回答

1

alpha和layer.opacity的更正是不必要的,您也可以使用扩展程序完成:

   extension UIImageView{
       func makeBlurImage(imageView:UIImageView?)
       {
          let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.Dark)
          let blurEffectView = UIVisualEffectView(effect: blurEffect)
          blurEffectView.frame = imageView!.bounds
          blurEffectView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] // to support device rotation
          imageView?.addSubview(blurEffectView)
       }
    }

使用方法:

  let imageView = UIImageView(frame: CGRectMake(0, 100, 300, 400))
  let image:UIImage = UIImage(named: "photo.png")!
  imageView.image =  image
  //Apply blur effect
  imageView.makeBlurImage(imageView)
  self.view.addSubview(imageView)

但是如果您想将模糊效果应用于UIView,则可以使用以下代码:

protocol Blurable
{
    var layer: CALayer { get }
    var subviews: [UIView] { get }
    var frame: CGRect { get }
    var superview: UIView? { get }

    func addSubview(view: UIView)
    func removeFromSuperview()

    func blur(blurRadius blurRadius: CGFloat)
    func unBlur()

    var isBlurred: Bool { get }
}

extension Blurable
{
    func blur(blurRadius blurRadius: CGFloat)
    {
        if self.superview == nil
        {
            return
        }

        UIGraphicsBeginImageContextWithOptions(CGSize(width: frame.width, height: frame.height), false, 1)

        layer.renderInContext(UIGraphicsGetCurrentContext()!)

        let image = UIGraphicsGetImageFromCurrentImageContext()

        UIGraphicsEndImageContext();

        guard let blur = CIFilter(name: "CIGaussianBlur"),
            this = self as? UIView else
        {
            return
        }

        blur.setValue(CIImage(image: image), forKey: kCIInputImageKey)
        blur.setValue(blurRadius, forKey: kCIInputRadiusKey)

        let ciContext  = CIContext(options: nil)

        let result = blur.valueForKey(kCIOutputImageKey) as! CIImage!

        let boundingRect = CGRect(x:0,
            y: 0,
            width: frame.width,
            height: frame.height)

        let cgImage = ciContext.createCGImage(result, fromRect: boundingRect)

        let filteredImage = UIImage(CGImage: cgImage)

        let blurOverlay = BlurOverlay()
        blurOverlay.frame = boundingRect

        blurOverlay.image = filteredImage
        blurOverlay.contentMode = UIViewContentMode.Left

        if let superview = superview as? UIStackView,
            index = (superview as UIStackView).arrangedSubviews.indexOf(this)
        {
            removeFromSuperview()
            superview.insertArrangedSubview(blurOverlay, atIndex: index)
        }
        else
        {
            blurOverlay.frame.origin = frame.origin

            UIView.transitionFromView(this,
                toView: blurOverlay,
                duration: 0.2,
                options: UIViewAnimationOptions.CurveEaseIn,
                completion: nil)
        }

        objc_setAssociatedObject(this,
            &BlurableKey.blurable,
            blurOverlay,
            objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
    }

    func unBlur()
    {
        guard let this = self as? UIView,
            blurOverlay = objc_getAssociatedObject(self as? UIView, &BlurableKey.blurable) as? BlurOverlay else
        {
            return
        }

        if let superview = blurOverlay.superview as? UIStackView,
            index = (blurOverlay.superview as! UIStackView).arrangedSubviews.indexOf(blurOverlay)
        {
            blurOverlay.removeFromSuperview()
            superview.insertArrangedSubview(this, atIndex: index)
        }
        else
        {
            this.frame.origin = blurOverlay.frame.origin

            UIView.transitionFromView(blurOverlay,
                toView: this,
                duration: 0.2,
                options: UIViewAnimationOptions.CurveEaseIn,
                completion: nil)
        }

        objc_setAssociatedObject(this,
            &BlurableKey.blurable,
            nil,
            objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
    }

    var isBlurred: Bool
    {
        return objc_getAssociatedObject(self as? UIView, &BlurableKey.blurable) is BlurOverlay
    }
}

extension UIView: Blurable
{
}

class BlurOverlay: UIImageView
{
}

struct BlurableKey
{
    static var blurable = "blurable"
}

Swift 4.x

extension UIView {
struct BlurableKey {
    static var blurable = "blurable"
}

func blur(radius: CGFloat) {
    guard let superview = superview else { return }

    UIGraphicsBeginImageContextWithOptions(CGSize(width: frame.width, height: frame.height), false, 1)

    layer.render(in: UIGraphicsGetCurrentContext()!)

    guard let image = UIGraphicsGetImageFromCurrentImageContext() else { return }

    UIGraphicsEndImageContext()

    guard let blur = CIFilter(name: "CIGaussianBlur") else { return }

    blur.setValue(CIImage(image: image), forKey: kCIInputImageKey)
    blur.setValue(radius, forKey: kCIInputRadiusKey)

    let ciContext  = CIContext(options: nil)
    guard let result = blur.value(forKey: kCIOutputImageKey) as? CIImage else { return }
    let boundingRect = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
    guard let cgImage = ciContext.createCGImage(result, from: boundingRect) else { return }
    let filteredImage = UIImage(cgImage: cgImage)

    let blurOverlay = UIImageView()
    blurOverlay.frame = boundingRect

    blurOverlay.image = filteredImage
    blurOverlay.contentMode = UIViewContentMode.left

    if let stackView = superview as? UIStackView, let index = stackView.arrangedSubviews.index(of: self) {
        removeFromSuperview()
        stackView.insertArrangedSubview(blurOverlay, at: index)

    } else {
        blurOverlay.frame.origin = frame.origin

        UIView.transition(from: self,
                          to: blurOverlay,
                          duration: 0.2,
                          options: UIViewAnimationOptions.curveEaseIn,
                          completion: nil)
    }

    objc_setAssociatedObject(self,
                             &BlurableKey.blurable,
                             blurOverlay,
                             objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}

func unBlur() {
    guard let blurOverlay = objc_getAssociatedObject(self, &BlurableKey.blurable) as? UIImageView else { return }

    if let stackView = blurOverlay.superview as? UIStackView, let index = stackView.arrangedSubviews.index(of: blurOverlay) {
        blurOverlay.removeFromSuperview()
        stackView.insertArrangedSubview(self, at: index)

    } else {
        frame.origin = blurOverlay.frame.origin

        UIView.transition(from: blurOverlay,
                          to: self,
                          duration: 0.2,
                          options: UIViewAnimationOptions.curveEaseIn,
                          completion: nil)
    }

    objc_setAssociatedObject(self,
                             &BlurableKey.blurable,
                             nil,
                             objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}

var isBlurred: Bool {
    return objc_getAssociatedObject(self, &BlurableKey.blurable) is UIImageView
}
}

使用示例:

segmentedControl.unBlur()
segmentedControl.blur(blurRadius: 2)

这是Blurable项目的源代码。
你可以在他的GitHub项目这里找到更多细节。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接