UIVisualEffectView不会模糊它的SKView超级视图

时间:2014-07-27 11:13:36

标签: ios sprite-kit blur skview

我正在编写一个SpriteKit游戏,并且遇到了一个模糊视图的问题,它位于SKView上。它应该在游戏暂停时从右侧滑动,它应该像iOS 7中的控制中心面板一样模糊其父视图(SKView)的内容。这是所需的外观:

enter image description here

我实际得到的是:

enter image description here

实际上左边的视图并不是完全黑色的,你可以看到超视图中的高光是如何在几乎不透明的子视图中略微挣扎,但是没有应用模糊。它是iOS 8的bug /功能,还是我的错误/误解

这是我的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(view:SKView)中:

view.addSubview(optionsView)

按下暂停按钮:

self.optionsView.show()

P.S。虽然我知道另外两种实现模糊视图的方法,但我认为这个方法最简单,因为我的应用程序只支持iOS8

  1. 从superview渲染模糊的静态图像 - > 将UIImageView放在OptionsView上,其中clipsToBounds = true - > 动画UIImageView位置,同时为optionsView位置设置动画,使模糊相对于superview保持相对

  2. 忘掉UIView,UIVisualEffectView和UIBlurView,并将SKEffectNode与SKCropNode一起使用。

2 个答案:

答案 0 :(得分:2)

好的,我已经设法使用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
    }
}

结果:

enter image description here

虽然有几个问题

  1. 裁剪不能与SKEffectNode一起使用,直到它的shouldRasterize属性设置为true。我让整个屏幕变得模糊。所以我仍然不知道如何正确实现实时模糊。

  2. BlurCropNode上的动画不够流畅。由于捕获纹理并将其设置为effectNode的精灵子,因此在开始时存在滞后。甚至dispatch_async都没有帮助。

  3. 如果有人能帮助解决至少一个问题,我们将非常感激

答案 1 :(得分:1)

我知道我可能有点迟了但我遇到了同样的问题,并找到了在屏幕的一部分上创建实时模糊的解决方案。它基于本教程: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)
}

然后,您必须捕获要模糊的视图部分,并将SKTexture应用于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左右,所以它显然不适合某些东西,但希望它有所帮助。