I am trying to animate a line drawing on a path using SpriteKit. I implemented a working solution using SKActions and a separate implementation using CABasicAnimations. The SKAction solution is not very elegant; it creates and starts a new path on each iteration of the SKAction.repeatAction call (action: count :) with each new path, a little more complete than the previous one.
func start() { var i:Double = 1.0 let spinAction:SKAction = SKAction.repeatAction(SKAction.sequence([ SKAction.runBlock({ self.drawCirclePercent(i * 0.01) if (++i > 100.0) { i = 1.0 } }), SKAction.waitForDuration(0.01) ]), count: 100) runAction(spinAction) } func drawCirclePercent(percent:Double) { UIGraphicsBeginImageContext(self.size) let ctx:CGContextRef = UIGraphicsGetCurrentContext() CGContextSaveGState(ctx) CGContextSetLineWidth(ctx, lineWidth) CGContextSetRGBStrokeColor(ctx, 1.0, 1.0, 1.0, 1.0) CGContextAddArc(ctx, CGFloat(self.size.width/2.0), CGFloat(self.size.height/2.0), radius/2.0, CGFloat(M_PI * 1.5), CGFloat(M_PI * (1.5 + 2.0 * percent)), 0) CGContextStrokePath(ctx) let textureImage:UIImage = UIGraphicsGetImageFromCurrentImageContext() texture = SKTexture(image: textureImage) UIGraphicsEndImageContext() }
While the code above works, it certainly is not pretty or efficient, and you should probably not use SKActions. The CABasicAnimation solution is much more elegant and much more efficient.
let path:CGMutablePathRef = CGPathCreateMutable() CGPathAddArc(path, nil, 0, 0, 40.0, CGFloat(M_PI_2 * 3.0), CGFloat(M_PI_2 * 7.0), false) let pathLayer:CAShapeLayer = CAShapeLayer() pathLayer.frame = CGRectMake(100, 100, 80.0, 80.0) pathLayer.path = path pathLayer.strokeColor = SKColor.whiteColor().CGColor pathLayer.fillColor = nil pathLayer.lineWidth = 3.0 self.view.layer.addSublayer(pathLayer) let pathAnimation:CABasicAnimation = CABasicAnimation(keyPath: "strokeEnd") pathAnimation.duration = 2.0 pathAnimation.fromValue = 0.0 pathAnimation.toValue = 1.0 pathLayer.addAnimation(pathAnimation, forKey: "strokeEndAnimation")
My problem is that I would really prefer all the code to be contained in a subclass of SKSpriteNode (so much so that if the two solutions above are the only options I have, I would go with the first one). Is there a way by which I can improve the SKAction implementation to more closely resemble the CoreAnimation implementation, without having to enable CoreAnimation? Essentially, I wonder if SpriteKit has functionality that I don't know about that can be used to improve the first implementation.