Resize sprite without shrinking contents

送分小仙女□ 提交于 2019-12-20 04:22:10

问题


I have created a big circle with a UIBezierPath and turned it into a Sprite using this,

let path = UIBezierPath(arcCenter: CGPoint(x: 0, y: 0), radius: CGFloat(226), startAngle: 0.0, endAngle: CGFloat(M_PI * 2), clockwise: false)

// create a shape from the path and customize it
let shape = SKShapeNode(path: path.cgPath)
shape.lineWidth = 20
shape.position = center
shape.strokeColor = UIColor(red:0.98, green:0.99, blue:0.99, alpha:1.00)

let trackViewTexture = self.view!.texture(from: shape, crop: outerPath.bounds)
let trackViewSprite = SKSpriteNode(texture: trackViewTexture)
trackViewSprite.physicsBody = SKPhysicsBody(edgeChainFrom: innerPath.cgPath)
self.addChild(trackViewSprite)

It works fine. It creates the circle perfectly. But I need to resize it using

SKAction.resize(byWidth: -43, height: -43, duration: 0.3)

Which will make it a bit smaller. But, when it resizes the 20 line width I set now is very small because of the aspect fill. So when I shink it looks something like this:

But I need it to shrink like this-- keeping the 20 line width:

How would I do this?

Don't know if this would affect anything, but the sprites are rotating with an SKAction forever

-- EDIT -- Now, how do I use this method to scale to a specific size? Like turn 226x226 to 183x183?


回答1:


Since by scaling down the circle, not only its radius gets scaled but its line's width too, you need to set a new lineWidth proportional with the scale. For example, when scaling the circle down by 2, you will need to double the lineWidth.

This can be done in two ways:

  1. Setting the lineWidth in the completion block of the run(SKAction, completion: @escaping () -> Void) method. However this will result in seeing the line shrinking while the animation is running, then jumping to its new width once the animation finishes. If your animation is short, this may not be easy to observe tough.

  2. Running a parallel animation together with the scaling one, which constantly adjusts the lineWidth. For this, you can use SKAction's customAction method. Here is an example for your case:

    let scale = CGFloat(0.5)
    let finalLineWidth = initialLineWidth / scale
    let animationDuration = 1.0
    
    let scaleAction = SKAction.scale(by: scale, duration: animationDuration)
    
    let lineWidthAction = SKAction.customAction(withDuration: animationDuration) { (shapeNode, time) in
        if let shape = shapeNode as? SKShapeNode {
            let progress = time / CGFloat(animationDuration)
    
            shape.lineWidth = initialLineWidth + progress * (finalLineWidth - initialLineWidth)
        }
    }
    
    let group = SKAction.group([scaleAction, lineWidthAction])
    
    shape.run(group)
    

In this example, your shape will be scaled by 0.5, therefore in case of an initial line width of 10, the final width will be 20. First we create a scaleAction with a specified duration, then a custom action which will update the line's width every time its actionBlock is called, by using the progress of the animation to make the line's width look like it's not changing. At the end we group the two actions so they will run in parallel once you call run.

As a hint, you don't need to use Bezier paths to create circles, there is a init(circleOfRadius: CGFloat) initializer for SKShapeNode which creates a circle for you.



来源:https://stackoverflow.com/questions/40072071/resize-sprite-without-shrinking-contents

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!