Skip to content

Instantly share code, notes, and snippets.

@styrken
Created September 14, 2018 19:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save styrken/13f0dfe663825caa26cb96bc3bcd8669 to your computer and use it in GitHub Desktop.
Save styrken/13f0dfe663825caa26cb96bc3bcd8669 to your computer and use it in GitHub Desktop.
SpriteKit: Resizable circle with a ripple effect animation
//
// 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