ios Sprite Kit скриншот?

Я пытаюсь получить снимок экрана с изображением SKScene. Техника, которую я использую:

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, scale);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Это прекрасно работает с обычными UIViews, но по любой причине игнорирует все спрайты в SKScene.

Я не уверен, является ли это ошибкой или рендеринг Sprite Kit отделен от UIGraphics.

Вопрос: Как получить снимок экрана SKScene, когда способ, который работал для UIViews, кажется, не работает с Sprite Kit, или кто-то имел успех, используя контекст UIGraphics с Sprite Kit?

4 ответа

Решение

У вас почти это есть, но проблема в том, как описано в комментарии выше. Если вы хотите захватить SKScene содержимое, попробуйте что-то вроде этого:

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, scale);
[self.view drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Решение состоит в том, чтобы в основном использовать новый метод drawViewHierarchyInRect:afterScreenUpdates вместо этого, что является лучшим, что мы имеем на данный момент; обратите внимание, это не совсем быстро, так что делать это в режиме реального времени будет не очень приятно.

В качестве более быстрой альтернативы вы можете использовать textureFromNode метод на SKView, который возвращает изображение вида в виде SKTexture, Просто передать SKScene в качестве аргумента:

let texture = skView.textureFromNode(scene)

Или захватить часть сцены:

let texture = skView.textureFromNode(scene, crop: cropRect)

//1: получить текстуру из "someNode"

let texture = skView.textureFromNode(someNode)

// 2: получить UIImage из текстуры узла

let image = UIImage(cgImage: texture!.cgImage())

Решение для Swift:

func getScreenshot(scene: SKScene, duration:TimeInterval = 0.0001, completion:((_ txt:SKTexture) -> Void)?) {
    let action = SKAction.run {
        let bounds = scene.view?.bounds
        var image = UIImage()
        UIGraphicsBeginImageContextWithOptions(bounds!.size, true, UIScreen.main.scale)
        scene.view?.drawHierarchy(in: bounds!, afterScreenUpdates: true)
        if let screenshot = UIGraphicsGetImageFromCurrentImageContext() {
            UIGraphicsEndImageContext()
            image = screenshot
        } else {
            assertionFailure("Unable to make a screenshot for the scene \(type(of:scene))")
        }
        completion!(SKTexture(image: image))
    }
    let wait = SKAction.wait(forDuration: duration)
    let seq = SKAction.sequence([wait,action])
    scene.run(seq,withKey:"getScreenshot")
}

Использование:

getScreenshot(scene: self, completion:{ (txt) -> Void in
            let thumbNode = SKSpriteNode(texture: txt, size:CGSize(width:300,height:224))
            // do whatever you want with your screenshot..
}
Другие вопросы по тегам