如何在iOS中为高斯模糊效果设置animation效果?

对于整个iOS 7的感觉,我想要在屏幕的特定部分应用模糊效果来对其进行混淆,但是我不想立即将模糊处理掉,我想要对其进行animation处理并将其制作为animation效果用户几乎看到正在应用的模糊效果。

就像在Photoshop中一样,您可以将高斯模糊值从0改为10,而不是0到10。

我已经尝试了一些解决scheme,最stream行的build议是将模糊视图放在非模糊视图的顶部,然后降低模糊视图的alpha值。

这工作正常 ,但不是很令人愉快,因为没有过渡,这只是一个覆盖。 例:

在这里输入图像说明

什么是更好的方法来达到这样的效果? 我熟悉GPUImage ,但不知道如何做到这一点。

如果我能够控制模糊的百分比,那也是很好的,所以可以从用户那里交互地应用。 (例如:用户中途拖动,模糊一半,等等)

使用iOS 9或更高版本,可以在视觉效果视图上为其生成animation效果:

[UIView animateWithDuration:0.3 animations: ^ { visualEffectView.effect = blurEffect; } completion:nil]; 

这将达到animation模糊半径的预期效果。


我认为如果你从非模糊的视图 – >模糊的视图进行交叉淡入淡出,那将会是令人满意的。 您需要在非模糊视图顶部将模糊视图的显示animation化。

假设blurView是包含模糊效果的视图。

以下是如何完成animation过渡的两个示例:

 [UIView transitionWithView:self.view duration:0.3 options:UIViewAnimationOptionTransitionCrossDissolve animations: ^ { [self.view addSubview:blurView]; } completion:nil]; 

这里我假设blurView已经被设置好了,只需要在animation中添加子视图。

你也可以用不同的方式实现这一点:

 blurView.alpha = 0.0f; [UIView animateWithDuration:0.3 animations: ^ { blurView.alpha = 1.0f; } completion:nil]; 

在这里,我使模糊视图变得透明,并使其外观animation化。 注意,使用这个方法不能用于hidden ,所以你想使用alpha属性。


如果你想交互地控制模糊量,这里是一个如何实现的例子:

首先创build你想要模糊的视图的图像:

 UIGraphicsBeginImageContextWithOptions(nonBlurredView.bounds.size, NO, self.view.window.screen.scale); [nonBlurredView drawViewHierarchyInRect:nonBlurredView.bounds afterScreenUpdates:NO]; UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext(); 

保持这个形象。 如果视图已更改,则只想以类似的方式重新绘制。 否则,你应该重用这个图像,因为绘制层次结构是昂贵的。

现在,当你需要模糊时,使用下面的代码:

 CIImage *imageToBlur = [CIImage imageWithCGImage:snapshotImage.CGImage]; CIFilter *gaussianBlurFilter = [CIFilter filterWithName: @"CIGaussianBlur"]; [gaussianBlurFilter setValue:imageToBlur forKey: @"inputImage"]; [gaussianBlurFilter setValue:@10 forKey: @"inputRadius"]; //Here you input the blur radius - the larger, the CIImage *resultImage = [gaussianBlurFilter valueForKey: @"outputImage"]; UIImage *endImage = [[UIImage alloc] initWithCIImage:resultImage]; 

inputRadiusinput可以设置所执行的模糊量。 如果你有这个animation,你将获得一个互动的感觉。

但我仍然认为以前的方法要容易得多,对用户也会感觉不错。

在OS X上这很容易,其中一个视图可以对后面的视图进行CIFilter效果,以及处理器function强大且快速的位置。 然而,在iOS上,没有视图合成filter,而且模糊需要一些时间:不能重复执行,而是像animation帧一样快。 因此需要某种forms的妥协。

如果事先知道了要模糊的东西,那么可以使用模糊渐变来准备一系列图像:不模糊,模糊,模糊,等等。 然后你组装这些图像,并把它们作为animationUIImageView的“框架”来“玩”它们。

但是,这不是我真正build议的。 我要做的是准备模糊图像和非模糊图像,并使用CIDissolveTransition从非模糊图像溶解到模糊图像。 不,这与逐渐应用模糊不一样,但它在计算上是便宜的,并且是工具箱中最好的“消除”效果。

我很lessbuild议现成解决scheme的编码问题。 不过,在这种情况下,我会全心全意推荐LiveFrost 。 这是一个非常可靠的UIView子类,专门用于复制stream行的iOS 7高斯模糊效果。

我也鼓励你阅读作者的博客,关于他的这个课程的devise决定。 自从iOS 7发布以来,我在这个主题上做了大量的研究,而且我对这个代码有了直接的抱怨。

它甚至有模糊animation开箱! 祝你好运 :)

我开发了一个小项目,使用GPUImage来模糊模糊半径和帧速率( MSLiveBlur ),这听起来正是你所需要的。

在示例应用程序中,我有一个滑块,可以根据用户操作增加/减less模糊级别,正如您在问题中提到的那样。 如果您想在没有用户交互的情况下进行animation制作,您可以制作一个计时器,以缓慢增加模糊半径,直到达到最终值。 尽pipe如此,您仍然无法使用CoreAnimation。

 [[MSLiveBlurView sharedInstance] setBlurInterval:0.2]; [[MSLiveBlurView sharedInstance] blurRect:someView.frame]; // Count x from 0 to your final radius [MSLiveBlurView sharedInstance].blurRadius = x; 

这里有一个function,你可以使用预先计算的图像animation模糊。 你说你熟悉GPUImage,所以我用它(但它也可以用简单的模糊algorithm)。

有了这个,你可以dynamic实时模拟animation,花费1-2%的CPU

 // configuration let imageCount: Int = 10 let blurMax: Float = 40.0 // keep images in memory var currentIdx: Int = 0 var imgs: [UIImage] = [] // func that create the precomputed images with GPUImage (call it in the viewDidLoad for example) func initBlur() { let blur = GaussianBlur() let myImage: UIImage = UIImage(named: "your_image")! let pictureInput = PictureInput(image: myImage) let pictureOutput = PictureOutput() pictureOutput.onlyCaptureNextFrame = false pictureOutput.imageAvailableCallback = { image in self.imgs.append(image) } pictureInput --> blur --> pictureOutput for i in 0...imageCount { blur.blurRadiusInPixels = (Float(i) / Float(imageCount)) * blurMax pictureInput.processImage(synchronously: true) } } // function that return the correct image from the image set with a blur percentage from a value between 0 and 1 where 0 = no blur and 1 full blurred. func getBlurredImage(value: Float) -> UIImage? { // return nil if there isn't precompiled images if imgs.count == 0 { return nil } // get the desired blurred image index let idx = Int(value * Float(imageCount - 1)) // if the index changed, check the correctness of the index if currentIdx != idx { if idx < 0 { currentIdx = 0 } else if idx >= imgs.count { currentIdx = imageCount - 1 } else { currentIdx = idx } } return imgs[currentIdx] } 

就这样,接下来你可以使用它,例如一个定时器或scrollViewDidScroll函数,如:

 imageView.image = getBlurredImage(value: yOffset / height)