Search code examples
iosswiftskviewaspect-fit

Display aspect fit Video and Image in SKView


I was struggling to display aspect fit images using SKSpriteNode in SKView. I faced many issues, such as size issues, can't place images of specific origin, etc. Same problem I had to display video using SKVideoNode in SKView.


Solution

  • // Assign Image URL to SKTexture
      func PictureSection() {
         let sceneImageFeedTexture = SKTexture(image:url)
         let pictureBoxImage = SKSpriteNode(texture: sceneImageFeedTexture)
         pictureBoxImage.anchorPoint = CGPoint(x: 0, y: 0)
         pictureBoxImage.aspectFillToSizeForImage(fillSize: CGSize(width: size.width, height: size.height)) // Do this after you set texture
         let imageY = (skviewcontainerheight - pictureBoxImage.size.height)/2
         pictureBoxImage.position = CGPoint(x: (size.width-pictureBoxImage.size.width)/2, y: imageY)
         addChild(pictureBoxImage)
    }
    //Calulate Image size
    extension SKSpriteNode {
    func aspectFillToSizeForImage(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)
        }
    }
    }
    
    
    //Assign Video
    func VideoBox{
     let player2 = AVPlayer(url: url as URL)
     let videoNode = SKVideoNode(avPlayer: player2)
     videoNode.position = CGPoint(x: frame.size.width/2, y: frame.size.height/2)
     videoNode.size = resolutionForLocalVideo(url:url)!
     videoNode.size = finalVideoSize(skvideo: videoNode)
     addChild(videoNode)
     videoNode.play()
    }
    func resolutionForLocalVideo(url:URL)-> CGSize? {
        guard let track = AVURLAsset(url: url).tracks(withMediaType: AVMediaType.video).first else {return nil}
        let size = track.naturalSize.applying(track.preferredTransform)
         return CGSize(width: abs(size.width), height: abs(size.height))
     }
    
    func finalVideoSize(skvideo:SKVideoNode)-> CGSize{
        let horizontalRatio = self.size.width / skvideo.size.width
        let verticalRatio = AppDelegate.shared.imageHeight! / skvideo.size.height
        let finalRatio = horizontalRatio < verticalRatio ? horizontalRatio : verticalRatio
        let size1 = CGSize(width: skvideo.size.width * finalRatio, height: skvideo.size.height * finalRatio)
        return size1
    }