调整精灵大小而不缩小内容 [英] Resize sprite without shrinking contents

查看:144
本文介绍了调整精灵大小而不缩小内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个带有UIBezierPath的大圆圈并使用它将其转换为精灵,

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

//创建一个形状从路径和自定义它
let shape = SKShapeNode(路径:path.cgPath)
shape.lineWidth = 20
shape.position = center
shape.strokeColor = UIColor(红色:0.98,绿色:0.99,蓝色:0.99,alpha:1.00)

让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,身高:-43,持续时间:0.3)

这将使它变得更小。但是,当它调整20行宽时,由于纵横填充,我现在设置的非常小。所以,当我眨眼它看起来像这样:





但是我需要它像这样缩小 - 保持20行宽:





我该怎么做?



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



- 编辑 -
现在,如何使用此方法扩展到特定大小?比如将226x226转为183x183?

解决方案

由于通过缩小圆圈,不仅其半径会缩放,而且线宽也是如此,你需要设置一个与比例成正比的新线宽。例如,当将圆圈缩小2时,您需要将lineWidth加倍。



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


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


  2. 与缩放动画一起运行并行动画,不断调整lineWidth。为此,您可以使用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)在
    中,如果让shape = shapeNode为? 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 时更新行的宽度,方法是使用动画的进度来使线条的宽度看起来不会改变。最后,我们将这两个操作分组,以便在您调用运行时它们将并行运行。



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


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?

解决方案

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.

这篇关于调整精灵大小而不缩小内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆