How do I place the SKSpriteNode in front of the CAShapeLayer?

I want to show SKSpriteNode in front of CAShapeLayer and this is the code I am using:

import SpriteKit
import GameplayKit
import UIKit

class GameScene: SKScene {

    let progressLayer = CAShapeLayer()

    override func didMove(to view: SKView) {

        let circle = UIView(frame: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
        view.addSubview(circle)
        view.sendSubview(toBack: circle)

        progressLayer.frame = view.bounds
        progressLayer.path = progressPath.cgPath

        progressLayer.fillColor = UIColor.clear.cgColor
        progressLayer.strokeColor = UIColor.green.cgColor
        progressLayer.lineWidth = 20.0

        let animation2 = CABasicAnimation(keyPath: "strokeEnd")
        animation2.fromValue = 0.0
        animation2.toValue = 1.0
        animation2.duration = 1
        animation2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)

        progressLayer.add(animation2, forKey: "drawLineAnimation")

        circle.layer.addSublayer(progressLayer)

        var popup = SKSpriteNode(imageNamed: "popupWorking.png")
        popup.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        popup.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
        popup.size = CGSize(width: 400, height: 200)
        popup.zPosition = 10
        self.addChild(popup)
    }
}

      

But when I run the code the CAShapeLayer appears in front of the SKSpriteNode, how can I make the SKSpriteNode in front of the CAShapeLayer?

+3


source to share


2 answers


You will need to change the view hierarchy at the controller level. By default, the View Manager view is SKView

. If you want to place another UIView

behind SKView

yours, you will need to adjust the view hierarchy.

Change the view of the view controller like UIView

instead SKView

. Then add the shape view representation as a peek to this main view. Then add the SKView

main view as a peek.

Your new view hierarchy should look like this:



View Controller
    – view (UIView)
        - circle view (UIView with your CAShapeLayer as a sublayer)
        - spritekit view (SKView)

      


Although it is possible to combine UIKit

and SpriteKit

thus may be easier to stay in the world SpriteKit

and to recreate the circle animation using SKSpriteNode

instead CAShapeLayer

.

+2


source


Here's a playground that shows one way to do it. I followed @ nathan's suggestion.

The yellow line is drawn using SKShapeNode. The red shadow needs to be animated behind it and therefore uses the CAShapeLayer. (Note: I needed to blend the two as the animated shadow path would be much more difficult in pure Sprite)



import SpriteKit
import PlaygroundSupport

private func invert(_ path: CGMutablePath)  -> CGPath {
    var rotation = CGAffineTransform(scaleX: 1.0, y: -1.0);
    return path.copy(using: &rotation)!;
}

let bounds = CGRect(x: 0, y: 0, width: 400, height: 200)
let uiview = UIView(frame: bounds)
let pathview = UIView(frame: bounds)
let skview = SKView(frame: bounds)

PlaygroundPage.current.liveView = uiview


// Define the path
let path: CGMutablePath = CGMutablePath();
path.move(to: CGPoint(x:0, y:0))
path.addLine(to: CGPoint(x:200, y:100))


// Use CAShapeLayer to draw the red line
var pathLayer: CAShapeLayer = CAShapeLayer()
pathLayer.position = CGPoint(x: uiview.bounds.minX, y: uiview.bounds.minY + 200)
pathLayer.path = invert(path)
pathLayer.strokeColor = UIColor.red.cgColor
pathLayer.fillColor = nil
pathLayer.lineWidth = 10.0
pathLayer.lineJoin = kCALineJoinBevel
pathLayer.lineCap = kCALineCapRound
pathLayer.zPosition = 3;
let strokeAnimation = CABasicAnimation(keyPath: "strokeAnimation")
strokeAnimation.duration = 2;
strokeAnimation.fromValue = 0;
pathview.layer.addSublayer(pathLayer);
pathLayer.add(strokeAnimation, forKey: "strokePath");

uiview.addSubview(pathview)

//Use SKShapeNode to draw the yellow line
let pathShape: SKShapeNode = SKShapeNode(path: path);
pathShape.strokeColor = .white;
pathShape.lineWidth = 2.0;
pathShape.zPosition = 20;

// Create SK Scene
let scene = SKScene(size: CGSize(width: 400, height: 200))
scene.scaleMode = SKSceneScaleMode.aspectFill
scene.size = skview.bounds.size
scene.addChild(pathShape);
scene.backgroundColor = UIColor.clear;
skview.backgroundColor = UIColor.clear


skview.presentScene(scene);
uiview.insertSubview(skview, aboveSubview: pathview)

      

0


source







All Articles