SpriteKit:使用SKShapeNode UIBezierPath圆角的Square to Circle动画

问题描述 投票:0回答:2

我试图在SpriteKit平滑地将一个正方形变成一个圆圈。

我用SKShape用圆角创造了UIBezierPath。然后,我将角半径改为动画。

我的问题是我似乎在动画中跳了一下,请看下面的gif。最好使用圆角技术,我怎样才能让它变得光滑?

“跳跃”的问题

    let shape = SKShapeNode()
    let l: CGFloat = 100.0
    shape.path = UIBezierPath(roundedRect: CGRect(x: -l/2, y: -l/2, width: l, height: l), byRoundingCorners: [.topLeft, .bottomLeft, .topRight, .bottomRight], cornerRadii: CGSize(width: 0, height: 0)).cgPath
    shape.position = CGPoint(x: frame.midX, y: frame.midY)
    shape.fillColor = .white
    addChild(shape)

    let action = SKAction.customAction(withDuration: 1) { (node, t) in
    let shapeNode = node as! SKShapeNode
    shapeNode.path = UIBezierPath(roundedRect: CGRect(x: -l/2, y: -l/2, width: l, height: l), byRoundingCorners: [.topLeft, .bottomLeft, .topRight, .bottomRight], cornerRadii: CGSize(width: t * l / 2, height: 0)).cgPath
    }
    shape.run(SKAction.repeatForever(action))

动画调试

要调试我已经创建了一些具有逐渐变大的角半径的形状,如下所示。数字表示角半径与正方形长度的比率。正如你所看到的,0.30.35之间有一个跳跃。我看不出我错过了什么。

    let cols = 10
    let rows = 1

    let l: Double = 30.0
    let max: Double = l / 2
    let delta: Double = l * 2

    for i in 0..<rows * cols {
        let s = SKShapeNode()
        let c: Double = Double(i % cols)
        let r: Double = floor(Double(i) / Double(cols))
        let pct: Double = Double(i) / (Double(rows) * Double(cols))
        let rad = pct * max
        s.path = UIBezierPath(roundedRect: CGRect(x: -l/2, y: -l/2, width: l, height: l), byRoundingCorners: [.topRight, .bottomRight, .topLeft, .bottomLeft], cornerRadii: CGSize(width: pct * max, height: pct * max)).cgPath
        s.position = CGPoint(x: c * delta - Double(cols) / 2.0 * delta, y: r * delta - Double(rows) / 2.0 * delta)
        s.lineWidth = 1.5
        s.strokeColor = .white
        addChild(s)

        let t = SKLabelNode(text: String(format:"%0.2f", rad / l))
        t.verticalAlignmentMode = .center
        t.horizontalAlignmentMode = .center
        t.fontName = "SanFrancisco-Bold"
        t.fontSize = 15

        t.position = CGPoint(x: 0, y: -delta * 0.66)
        s.addChild(t)
    }
ios swift sprite-kit
2个回答
1
投票

您可能无法使用当前的api找到答案。但你可以自己画画。

  let duration = 10.0
    let action = SKAction.customAction(withDuration: duration) { (node, t) in
      let shapeNode = node as! SKShapeNode
        let path = CGMutablePath()
        let borderRadius = l/2 * t  / CGFloat(duration);
      path.move(to: CGPoint.init(x: -l/2, y:  -l/2 + borderRadius));
      path.addLine(to: CGPoint.init(x:  -l/2, y: l/2 - borderRadius));
      path.addArc(tangent1End: CGPoint(x: -l/2, y: l/2), tangent2End: CGPoint(x: -l/2 + borderRadius, y: l/2), radius: borderRadius)
      path.addLine(to: CGPoint.init(x:  l/2 - borderRadius, y: l/2 ));
      path.addArc(tangent1End: CGPoint(x: l/2, y: l/2), tangent2End: CGPoint(x: l/2, y: l/2 - borderRadius), radius: borderRadius)
      path.addLine(to: CGPoint.init(x:  l/2, y: -l/2 + borderRadius));
      path.addArc(tangent1End: CGPoint(x: l/2, y: -l/2), tangent2End: CGPoint(x: l/2 - borderRadius, y: -l/2), radius: borderRadius)
      path.addLine(to: CGPoint.init(x:  -l/2 + borderRadius, y: -l/2));
      path.addArc(tangent1End: CGPoint(x: -l/2, y: -l/2), tangent2End: CGPoint(x: -l/2, y: -l/2 + borderRadius), radius: borderRadius)
      path.closeSubpath()
      shapeNode.path = path
    }

Working solution


0
投票

UIBezierPath.init(roundedRect:cornerRadius:)的文件指出:

每个角落的椭圆形半径。值为0会生成没有圆角的矩形。大于矩形宽度或高度一半的值被适当地夹紧到宽度或高度的一半。

但我测试了它,它实际上恰好发生在大于宽度/高度的三分之一的值而不是它的一半。我正在填写错误报告,希望它能很快得到解决。

错误报告链接:https://bugs.swift.org/browse/SR-10496

© www.soinside.com 2019 - 2024. All rights reserved.