【问题标题】:Resize sprite without shrinking contents调整精灵大小而不缩小内容
【发布时间】:2016-10-16 15:37:10
【问题描述】:

我用 UIBezierPath 创建了一个大圆圈,并使用它把它变成了 Sprite,

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)

它工作正常。它完美地创建了圆圈。但我需要使用

调整它的大小
SKAction.resize(byWidth: -43, height: -43, duration: 0.3)

这会使它变小一点。但是,当它调整我现在设置的 20 线宽时,由于纵横填充,它非常小。所以当我觉得它看起来像这样:

但我需要它像这样缩小——保持 20 线宽:

我该怎么做?

不知道这是否会影响任何事情,但精灵会永远随着 SKAction 旋转

-- 编辑-- 现在,如何使用此方法缩放到特定大小?比如把226x226转183x183?

【问题讨论】:

    标签: ios swift swift3 uibezierpath skspritenode


    【解决方案1】:

    由于通过缩小圆,不仅它的半径被缩放,它的线宽也被缩放,你需要设置一个与比例成比例的新 lineWidth。例如,将圆缩小 2 倍时,需要将 lineWidth 加倍。

    这可以通过两种方式完成:

    1. run(SKAction, completion: @escaping () -> Void) 方法的完成块中设置 lineWidth。然而,这将导致在动画运行时看到线条缩小,然后在动画完成后跳转到新的宽度。如果你的动画很短,这可能不容易观察到。

    2. 与缩放动画一起运行并行动画,不断调整线宽。为此,您可以使用 SKAction 的 customAction 方法。 这是您的案例的示例:

      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)
      

    在此示例中,您的形状将缩放 0.5,因此如果初始线宽为 10,最终宽度将为 20。首先我们创建一个具有指定持续时间的 scaleAction,然后创建一个自定义操作,该操作将更新每次调用actionBlock 时,线条的宽度,通过使用动画的进度使线条的宽度看起来没有变化。最后,我们将这两个操作分组,以便在您调用 run 时它们将并行运行。

    作为提示,您不需要使用 Bezier 路径来创建圆,SKShapeNode 有一个 init(circleOfRadius: CGFloat) 初始化程序,可以为您创建一个圆。

    【讨论】:

    • 这个小问题。我需要类型是 SKSpriteNode 而不是 SKShapeNode。也许我应该添加一个 SKAction,它将动画的 SKShapeNode 变成 SKSpriteNode?我用谷歌搜索了很多,据说 SKShapeNode 应该只用于调试或绘图。所以在它完成动画后我应该把它转换回来对吗?我也很想只使用 init(circleOfRadius) 但有些圆圈需要打开(比如 3/4 圆圈)。但是因为当我将 SKShapeNode 转换为纹理然后转换为精灵时,它会失去其线宽属性。所以我应该来回转换?
    • 如果您必须使用 SKSpriteNode,我认为唯一的解决方案是每次放大/缩小时在 SKShapeNode SKSpriteNode 之间进行转换。但是,如果您只需要显示简单的形状(全圆或空心圆),我会使用使用 Bezier 路径初始化的 SKShapeNode。这样,即使它是一个开放的圆圈,您也可以为线条的宽度设置动画。
    • 谢谢,我会做你所做的,并为此稍作改动。非常感谢!
    • 你的方法效果很好。但我被困住了。如何使用 scale 缩放到特定的 x 和 y?例如,我想把 226x226 变成 183x183。但是比例因子取一些随机值。我将如何获得我需要的确切价值?我试过183/226,但这不是正确的数字(?)
    • 你的逻辑不错,应该是183.0/226.0。如果你使用这个值会发生什么?
    猜你喜欢
    • 2011-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2021-02-23
    • 1970-01-01
    • 2023-03-06
    相关资源
    最近更新 更多