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.001

animation.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

キケ


0コメント

  • 1000 / 1000