Добавляем к ответу, так как OP явно запрашивала анимацию длины хода с течением времени, отмечая, что для этого нет SKAction. Вместо этого вы можете анимировать путь SKShapeNode путем предоставления настраиваемого strokeShader
, который выводит на основе нескольких из , SKShader и u_path_length
. Обратите внимание, что в шейдере, указанном ниже u_current_percentage
, мы добавили и ссылаемся на текущую точку в пути, к которому мы хотим погладить. При этом сцена определяет темп анимированного поглаживания. Также обратите внимание, что strokeShader
в качестве фрагментарного шейдера выводит RGB на каждом шагу, он позволяет вам управлять цветом по мере продвижения, позволяя, чтобы вы делали цвет градиента, если хотите.
Шейдер добавляется в виде файла в Xcode проекта animateStroke.fsh
:
void main()
{
if (u_path_length == 0.0) {
gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0); // draw blue // this is an error
} else if (v_path_distance/u_path_length <= u_current_percentage) {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // draw red
} else {
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); // draw nothing
}
}
и образец SKScene
подкласса, используя его:
import SpriteKit
import GameplayKit
func shaderWithFilename(_ filename: String?, fileExtension: String?, uniforms: [SKUniform]) -> SKShader {
let path = Bundle.main.path(forResource: filename, ofType: fileExtension)
let source = try! NSString(contentsOfFile: path!, encoding: String.Encoding.utf8.rawValue)
let shader = SKShader(source: source as String, uniforms: uniforms)
return shader
}
class GameScene: SKScene {
let strokeSizeFactor = CGFloat(2.0)
var strokeShader: SKShader!
var strokeLengthUniform: SKUniform!
var _strokeLengthFloat: Float = 0.0
var strokeLengthKey: String!
var strokeLengthFloat: Float {
get {
return _strokeLengthFloat
}
set(newStrokeLengthFloat) {
_strokeLengthFloat = newStrokeLengthFloat
strokeLengthUniform.floatValue = newStrokeLengthFloat
}
}
override func didMove(to view: SKView) {
strokeLengthKey = "u_current_percentage"
strokeLengthUniform = SKUniform(name: strokeLengthKey, float: 0.0)
let uniforms: [SKUniform] = [strokeLengthUniform]
strokeShader = shaderWithFilename("animateStroke", fileExtension: "fsh", uniforms: uniforms)
strokeLengthFloat = 0.0
let cameraNode = SKCameraNode()
self.camera = cameraNode
// make your rounded rect
let path = CGMutablePath()
path.addRoundedRect(in: CGRect(x: 0, y: 0, width: 200, height: 150), cornerWidth: 35, cornerHeight: 35, transform: CGAffineTransform.identity)
// note that prior to a fix in iOS 10.2, bug #27989113 "SKShader/SKShapeNode: u_path_length is not set unless shouldUseLocalStrokeBuffers() is true" requires that a path be "long" - past a certain number of points - I don't know how many. So if the rounded rect doesn't work for you on iOS 10 - iOS 10.1, try this path instead:
// let path1 = CGMutablePath()
// path1.move(to: CGPoint.zero)
// path1.addLine(to: CGPoint(x: 0, y: strokeHeight))
// for i in 0...15 {
// path.addLine(to: CGPoint(x: 0, y: strokeHeight + CGFloat(0.001) * CGFloat(i)))
// }
// path.closeSubpath()
let strokeWidth = 17.0 * strokeSizeFactor
let shapeNode = SKShapeNode(path: path)
shapeNode.lineWidth = strokeWidth
shapeNode.lineCap = .round
shapeNode.addChild(cameraNode)
shapeNode.strokeShader = strokeShader
shapeNode.calculateAccumulatedFrame()
addChild(shapeNode)
// center the camera
cameraNode.position = CGPoint(x: shapeNode.frame.size.width/2.0, y: shapeNode.frame.size.height/2.0)
}
override func update(_ currentTime: TimeInterval) {
// the increment chosen determines how fast the path is stroked. Note this maps to "u_current_percentage" within animateStroke.fsh
strokeLengthFloat += 0.01
if strokeLengthFloat > 1.0 {
strokeLengthFloat = 0.0
}
}
}
Я не знал, что вы могли бы назначить путь к «SKShapeNode» до сих пор, и я не знал, что до этого был идентификатор 'CGCreatePathWithRoundedRect'. Спасибо! – DDPWNAGE