Created
September 14, 2018 19:08
-
-
Save styrken/13f0dfe663825caa26cb96bc3bcd8669 to your computer and use it in GitHub Desktop.
SpriteKit: Resizable circle with a ripple effect animation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// RippleCircleNode.swift | |
// | |
// Created by Rasmus Styrk on 14/09/2018. | |
// Copyright © 2018 House of Code ApS. All rights reserved. | |
// | |
// Updated https://gist.github.com/gblancogarcia/4b8c22dd9f0272edde86 | |
// - Swift 4.2 | |
// - Made fade out a bit slower | |
// - Changed scale paramater to newRadius instead | |
// - Added completion to be called when animation finished so you can repeat the ripple | |
import SpriteKit | |
class RippleCircleNode: SKShapeNode { | |
var radius: CGFloat { | |
didSet { | |
self.path = RippleCircleNode.path(radius: self.radius) | |
} | |
} | |
init(radius: CGFloat, position: CGPoint) { | |
self.radius = radius | |
super.init() | |
self.path = RippleCircleNode.path(radius: self.radius) | |
self.position = position | |
} | |
required init?(coder aDecoder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
class func path(radius: CGFloat) -> CGMutablePath { | |
let path: CGMutablePath = CGMutablePath() | |
path.addArc(center: CGPoint(x: 0, y: 0), | |
radius: radius, | |
startAngle: 0.0, | |
endAngle: CGFloat(2.0 * M_PI), | |
clockwise: true) | |
return path | |
} | |
func ripple(to newRadius: CGFloat, duration: TimeInterval, completion: @escaping () -> ()) { | |
if let parent = self.parent { | |
let currentRadius = radius | |
let circleNode = RippleCircleNode(radius: radius, position: position) | |
circleNode.strokeColor = strokeColor | |
circleNode.fillColor = fillColor | |
circleNode.position = position | |
circleNode.zRotation = zRotation | |
circleNode.lineWidth = lineWidth | |
circleNode.isUserInteractionEnabled = false | |
if let index = parent.children.firstIndex(of: self) { | |
parent.insertChild(circleNode, at: index) | |
let scaleAction = SKAction.customAction(withDuration: duration, | |
actionBlock: { node, elapsedTime in | |
let circleNode = node as! RippleCircleNode | |
let fraction = elapsedTime / CGFloat(duration) | |
circleNode.radius = currentRadius + (fraction * newRadius) | |
}) | |
let fadeAction = SKAction.fadeAlpha(to: 0, duration: duration * 1.5) | |
fadeAction.timingMode = SKActionTimingMode.easeOut | |
let actionGroup = SKAction.group([scaleAction, fadeAction]) | |
circleNode.run(actionGroup, completion: { | |
circleNode.removeFromParent() | |
completion() | |
}) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment