Discover the New SFSymbols Animations Announced at WWDC24

AsyncLearn
3 min readAug 5, 2024

--

You need to use Xcode 16 Beta or later and iOS 18 Beta or later to use the new animations.

Last year at WWDC23, Apple announced animations for SFSymbols. This year at WWDC24, three new animations were announced:

  • Wiggle
  • Rotate
  • Breathe

Let’s look at how to use each of them.

Wiggle Animation

This animation allows us to highlight changes or points of action in our app. Symbols can animate left-to-right, top-to-bottom, clockwise, counterclockwise, or at a custom angle. Here’s an example:

var wiggleAnimation: some View {
VStack(spacing: 13) {
// 1
Image(systemName: "square.and.arrow.up")
.symbolEffect(.wiggle.up)
// 2
Image(systemName: "alarm.waves.left.and.right")
.symbolEffect(.wiggle.clockwise)
// 3
Image(systemName: "paperplane")
.symbolEffect(.wiggle.custom(angle: 315))
// 4
Image(systemName: "airplane")
.symbolEffect(.wiggle.left)
}
.font(.system(size: 30))
}
  1. We define that our animation goes from top to bottom. To achieve the opposite effect (bottom to top), use .symbolEffect(.wiggle.down).

2. We define that our animation goes clockwise. The opposite effect is achieved with .symbolEffect(.wiggle.counterClockwise).

3. We define the angle at which we want the animation to occur. In this case, we use an angle of 315, but you can vary this angle as desired.

4. We define that our animation goes left to right. To achieve the opposite effect, use .symbolEffect(.wiggle.right).

In the example above, the animations run indefinitely. To make them execute in response to an action, you can do the following:

import SwiftUI

struct ContentView: View {
// 1
@State var animate = false

var body: some View {
VStack(spacing: 13) {
// 2
Image(systemName: "square.and.arrow.up")
.symbolEffect(.wiggle.up, value: animate)
.font(.system(size: 30))
Button {
// 3
animate.toggle()
} label: {
Text("Animate")
}
}
}
}
  1. We create a state variable called animate, which will be of type Bool.

2. We use the initializer for symbolEffect that allows us to pass our state variable as a parameter, which will trigger the animation when this variable changes.

3. We create a button whose action will toggle the state of our variable.

Rotate Animation

With .rotate, symbols can animate clockwise, counterclockwise, or by layers. Here’s an example of each:

VStack(spacing: 13) {
// 1
Image(systemName: "airplane")
.symbolEffect(.rotate)
// 2
Image(systemName: "fan.desk")
.symbolEffect(.rotate.byLayer)
// 3
Image(systemName: "line.3.crossed.swirl.circle")
.symbolEffect(.rotate.counterClockwise)
// 4
Image(systemName: "gearshape.2")
.symbolEffect(.rotate.clockwise)
}
.font(.system(size: 30))
  1. Default animation, simply add .symbolEffect(.rotate) to get the animation.

2. Layer animation, useful for symbols with different layers, like “fan.desk”.

3. Counterclockwise animation.

4. Clockwise animation.

Like with the .wiggle animation, you can start the animation in response to an action by passing our state variable: .symbolEffect(.rotate.byLayer, value: animate).

Breathe Animation

Finally, we have the .breathe animation, which is very similar to the .pulse animation, with the difference that .breathe animates both the opacity and size of the symbol, while .pulse only animates the opacity. Here’s an example of both to see the difference:

VStack(spacing: 13) {
// 1
Image(systemName: "heart")
.symbolEffect(.breathe)
// 2
Image(systemName: "heart")
.symbolEffect(.pulse)
}
.font(.system(size: 30))
  1. We see the .breathe animation.

2. We see the .pulse animation.

In this type of animation, you can also pass the state variable .symbolEffect(.breathe, value: animate).

--

--

AsyncLearn
AsyncLearn

Written by AsyncLearn

Stay up-to-date in the world of mobile applications with our specialised blog.

No responses yet