Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SKTexture from UIImage that respects aspect ratio

I'm setting an image as the background for a SKScene with code similar to the following

/* In SKScene subclass */
background = SKSpriteNode()
background.anchorPoint = CGPointMake(0,1)
background.position = CGPointMake(0, size.height)
background.zPosition = Layer.Background
background.size = view!.bounds.size
background.texture = SKTexture(image: <# UIImage #>)
addChild(background)

This works to insert the image as a background for the scene, but if the image isn't the same aspect ratio as the background node, it is stretched to fill it.

(on the left is the result when an image is cropped to fit the aspect ratio of the SKSpriteNode, and on the right is the result when the image is of a different aspect ratio)

Is there a way to make the SKSpriteNode respect the original aspect ratio of the image, in the way that a UIImageView can be set to use UIViewContentModeScaleAspectFill?

EDIT Changed mention of UIViewContentModeScaleAspectFit to UIViewContentModeScaleAspectFill, got them mixed up.

like image 320
Ziewvater Avatar asked Dec 02 '22 17:12

Ziewvater


2 Answers

You can create an extension for SKSpriteNode to do this.

extension SKSpriteNode {

    func aspectFillToSize(fillSize: CGSize) {

        if texture != nil {
            self.size = texture!.size()

            let verticalRatio = fillSize.height / self.texture!.size().height
            let horizontalRatio = fillSize.width /  self.texture!.size().width

            let scaleRatio = horizontalRatio > verticalRatio ? horizontalRatio : verticalRatio

            self.setScale(scaleRatio)
        }
    }

}

To use it

let background = SKSpriteNode()
background.anchorPoint = CGPointMake(0,1)
background.position = CGPointMake(0, size.height)
background.texture = SKTexture(imageNamed: "1.png")
background.aspectFillToSize(view.frame.size) // Do this after you set texture
addChild(background)
like image 161
rakeshbs Avatar answered Dec 20 '22 07:12

rakeshbs


Rakeshbs's answer is great. But I think the key point of this solution is to change the size of SKSpriteNode dynamically. Don't need to sale the node . So I update his code as below

extension SKSpriteNode {
func aspectFillToSize(fillSize: CGSize) {
    if let texture = self.texture {
        let horizontalRatio = fillSize.width / texture.size().width
        let verticalRatio = fillSize.height / texture.size().height
        let finalRatio = horizontalRatio < verticalRatio ? horizontalRatio : verticalRatio
        size = CGSize(width: texture.size().width * finalRatio, height: texture.size().height * finalRatio)
    }
}

}

like image 43
Rufus Avatar answered Dec 20 '22 07:12

Rufus