Swift Fireworks
Recently I had some spare time at work and I had the chance to develop some playful animation for the app. In particular, an animation that I've been insisting for a long time to give a better feedback and at the same time excite/motivate the user to start using our app. This animation that I am talking about is a firework.
1. From the beginning
To start the story from the beginning, when we decided that could be good to include fireworks inside the app, we (developer team) presented some SpriteKit particles animation to the designers.
Source: http://www.knowstack.com/swift-caemittercell-caemitterlayer-fireworks/
The designer team decided that this kind of firework design (above image) didn't fit into the app, and they asked for something more graphical, more geometrical.
Which we (developer team) decided that was going to take more time to develop than expected and we push it away for some other time, so there were things more important to do at that moment.
2. Drawing a firework
Some weeks ago I decided to take that matter again into the field and decided to create a 2D animation using CoreAnimation. To do that, I took the gif's provided by the designers as a reference, specially the second one (2016 image).
The animation that I developed is a simple circular CAShapeLayer with a lineDashPattern modifying its line. In addition, a CAShapeLayer with doughnut form is attached to the mask of that circle (above image). The circle is the firework itself. Instead, the doughnut is only used as a mask to vanish the firework with an animation (explained in the next section).
Line Dash Patterned Circle
let firework: CAShapeLayer = CAShapeLayer()
firework.lineDashPattern = [sparkThickness, sparkSeparation] as [NSNumber]
let circlePath = UIBezierPath(arcCenter: CGPoint(x: radius, y: radius),radius: radius,
startAngle: CGFloat(0.0),
endAngle: CGFloat(Double.pi*2),
clockwise: false)
firework.path = circlePath.cgPath
firework.mask = mask(radius: radius)
Doughnut Mask
let mask: CAShapeLayer = CAShapeLayer()
let arcCenter = CGPoint(x: radius, y: radius)
let startAngle = CGFloat(0.0)let endAngle = CGFloat(Double.pi*2)
let donutPath = CGMutablePath()
donutPath.addArc(center: arcCenter,
radius: radius + radius*0.25,
startAngle: startAngle,
endAngle: endAngle,
clockwise: false)
donutPath.addArc(center: arcCenter,
radius: radius*0.75,
startAngle: startAngle,
endAngle: endAngle,
clockwise: false)
mask.path = donutPath
mask.fillRule = kCAFillRuleEvenOdd
3. Animating that firework
The firework and the firework mask have a different CABasicAnimation attached, both modifying their transfom.scale property. The first one to achieve a bursting effect, applied to the line dash patterned circle (sparkles). And the second one with the vanishing of the sparkles, applied to the mask with doughnut form inside the circle.
let animation = CABasicAnimation(keyPath: "transform.scale")
animation.duration = 0.5
animation.fromValue = 0.001animation.toValue = 1.0
firework.add(animation, forKey: "boom")
let maskAnimation = CABasicAnimation(keyPath: "transform.scale")
maskAnimation.duration = 2.0
maskAnimation.fromValue = 1.0
maskAnimation.toValue = 2.0
firework.mask?.add(maskAnimation, forKey: "vanish")
4. Creating a library of it
Once I got one firework, doing the rest was only a matter of position, color and sparkles customization, plus some firework memory handling.
I liked the effect so much that I decided to create a library to easy attach fireworks in any UIView. It's a really light library, you can check it out here:
https://github.com/enricmacias/SwiftFireworks
キケ