UIVisualEffectView 不会模糊它的 SKView 超级视图
Posted
技术标签:
【中文标题】UIVisualEffectView 不会模糊它的 SKView 超级视图【英文标题】:UIVisualEffectView doesn't blur it's SKView superview 【发布时间】:2014-09-18 18:16:48 【问题描述】:我正在编写一个 SpriteKit 游戏,但遇到了 SKView 上的视图模糊问题。它应该在游戏暂停时从右侧滑动,并且它应该模糊其父视图 (SKView) 的内容,就像 ios 7 中的控制中心面板一样。这是所需的外观:
我实际得到的是:
事实上,左边的视图并不是全黑的,你可以看到超视图的高光在几乎不透明的子视图中略微挣扎,但没有应用模糊。这是 iOS 8 的错误/功能,还是我的错误/误解
这是我的 UIVisualEffectView 子类的要点:
class OptionsView: UIVisualEffectView
//...
init(size: CGSize)
buttons = [UIButton]()
super.init(effect: UIBlurEffect(style: .Dark))
frame = CGRectMake(-size.width, 0, size.width, size.height)
addButtons()
clipsToBounds = true
func show()
UIView.animateWithDuration(0.3, animations:
self.frame.origin.x = 0
)
func hide()
UIView.animateWithDuration(0.3, animations:
self.frame.origin.x = -self.frame.size.width
)
然后在 GameScene 类中:
在初始化器中:
optionsView = OptionsView(size: CGSizeMake(130, size.height))
在 didMoveToView(视图:SKView)中:
view.addSubview(optionsView)
按下暂停键:
self.optionsView.show()
附:虽然我知道另外两种实现模糊视图的方法,但我认为这是最简单的一种,因为我的应用程序将仅支持 iOS8
从 superview 渲染一个模糊的静态图像 -> 将 UIImageView 放在 OptionsView 上,使用 clipsToBounds = true -> 在为 optionsView 位置设置动画时为 UIImageView 位置设置动画,以便模糊相对于超级视图保持静止
忘记 UIView、UIVisualEffectView 和 UIBlurView,将 SKEffectNode 与 SKCropNode 一起使用。
【问题讨论】:
sprite kit view不受uiview视觉效果影响,因为sk使用不同的渲染路径,在skview上使用effectnode效果 您也可以对SKView进行快照并将其放置为图像视图以能够显示此效果。 是的,这正是我在 P.S. 中的意思。 #1 【参考方案1】:好的,我已经设法使用 SKEffectNode 而不是 UIVisualEffectView 获得所需的效果。 这是面临相同问题的人的代码
class BlurCropNode: SKCropNode
var blurNode: BlurNode
var size: CGSize
init(size: CGSize)
self.size = size
blurNode = BlurNode(radius: 10)
super.init()
addChild(blurNode)
let mask = SKSpriteNode (color: UIColor.blackColor(), size: size)
mask.anchorPoint = CGPoint.zeroPoint
maskNode = mask
class BlurNode: SKEffectNode
var sprite: SKSpriteNode
var texture: SKTexture
get return sprite.texture
set
sprite.texture = newValue
let scale = UIScreen.mainScreen().scale
let textureSize = newValue.size()
sprite.size = CGSizeMake(textureSize.width/scale, textureSize.height/scale)
init(radius: CGFloat)
sprite = SKSpriteNode()
super.init()
sprite.anchorPoint = CGPointMake(0, 0)
addChild(sprite)
filter = CIFilter(name: "CIGaussianBlur", withInputParameters: ["inputRadius": radius])
shouldEnableEffects = true
shouldRasterize = true
结果:
有几个问题
在 SKEffectNode 的 shouldRasterize 属性设置为 true 之前,裁剪不能与 SKEffectNode 一起使用。我弄得整个屏幕都模糊了。所以我还是不知道如何正确实现实时模糊。
BlurCropNode 上的动画不够流畅。由于捕获纹理并将其设置为 effectNode 的子精灵,一开始会有延迟。即使 dispatch_async 也无济于事。
如果有人能帮助解决至少一个问题,我们将不胜感激
【讨论】:
【参考方案2】:我知道我可能有点晚了,但我遇到了同样的问题,并找到了在部分屏幕上创建实时模糊的解决方案。它基于本教程:http://www.youtube.com/watch?v=eYHId0zgkdE,他使用着色器来模糊静态精灵。我扩展了他的教程来捕捉屏幕的一部分,然后对其应用模糊。对于您的问题,您可以在该侧边栏下捕获。
首先,您创建一个SKSpriteNode
来保存捕获的纹理。然后在didMoveToView()
中将模糊着色器添加到该精灵。 (你可以在 GitHub 上找到 blur.fsh 文件,youtube 视频底部有一个链接。)
override func didMoveToView(view: SKView)
blurNode.shader = SKShader(fileNamed: "blur")
self.addChild(blurNode)
然后您必须捕获要模糊的视图部分,并将@987654325@ 应用于我的情况下为blurNode
。
override func update(currentTime: CFTimeInterval)
// Hide the blurNode to avoid it be captured too.
blurNode.hidden = true
blurNode.texture = self.view!.textureFromNode(self, crop: blurNode.frame)
blurNode.hidden = false
应该就是这样。在我的 iPad mini 上,模糊为屏幕宽度的 1/3,fps 为 58-59。使整个屏幕模糊,fps 下降到 22 左右,因此对于某些事情显然不是理想的,但希望它有所帮助。
【讨论】:
以上是关于UIVisualEffectView 不会模糊它的 SKView 超级视图的主要内容,如果未能解决你的问题,请参考以下文章
UIVisualEffectView 和 UITableView