在 UI 个元素上应用 CIFilter

Apply CIFilters on UI elements

我想在 UI 元素上应用 CIFilter。我试图通过 .filters 成员将它应用到视图层。但是不会应用过滤器。

这是一种方法:使用 UIGraphicsGetImageFromCurrentImageContext 生成 UIImage,对其应用滤镜并将包含滤镜图像的图像视图覆盖在原始组件上。

这是一种使用模糊 (taken from my blog) 的方法:

获取 UIView 的模糊表示非常简单:我需要开始图像上下文,使用视图层的 renderInContext 方法渲染到上下文中,然后从上下文中获取 UIImage:

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

layer.renderInContext(UIGraphicsGetCurrentContext()!)

let image = UIGraphicsGetImageFromCurrentImageContext()


UIGraphicsEndImageContext();

填充图像后,对其应用高斯模糊是一个相当标准的工作流程:

guard let blur = CIFilter(name: "CIGaussianBlur") 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: -blurRadius * 4,
    y: -blurRadius * 4,
    width: frame.width + (blurRadius * 8),
    height: frame.height + (blurRadius * 8))

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


let filteredImage = UIImage(CGImage: cgImage)

模糊图像将大于其输入图像,因此我需要在 createCGImage 中明确说明我需要的尺寸。

下一步是在我的视图中添加一个 UIImageView 并隐藏所有其他视图。我已将 UIImageView 子类化为 BlurOverlay,以便在删除它时,我可以确定我没有删除现有的 UIImageView

let blurOverlay = BlurOverlay()
blurOverlay.frame = boundingRect

blurOverlay.image = filteredImage

subviews.forEach{ [=12=].hidden = true }


addSubview(blurOverlay)

关于去模糊,我想确保最后一个子视图是我的 BlurOverlay 删除它并取消隐藏现有视图:

func unBlur()
{
    if let blurOverlay = subviews.last as? BlurOverlay
    {
        blurOverlay.removeFromSuperview()

        subviews.forEach{ [=13=].hidden = false }
    }

}

最后,要查看UIView当前是否模糊,我只需要查看其最后一个子视图是否为BlurOverlay:

var isBlurred: Bool
{
    return subviews.last is BlurOverlay
}