Resize sprite without shrinking contents

前端 未结 1 1703
悲&欢浪女
悲&欢浪女 2021-01-24 14:50

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(2         


        
1条回答
  •  夕颜
    夕颜 (楼主)
    2021-01-24 15:25

    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.

    0 讨论(0)
提交回复
热议问题