987 words • 4 minute read.
Last week, I wrote about SF Symbols and how to use them in your apps. If you missed it, you can check it out here. This week, we’ll dive into animating SF Symbols—because who doesn’t love a good animation?
Now, according to Apple documentation (straight from the docs, not my words), there are 4 different behaviour types:
An effect that runs from start to finish.
An effect that lasts until you remove or disable it.
An effect that animates a symbol in or out of visibility.
An effect that replaces one symbol with another symbol, or with a different configuration of itself.
This doesn’t mean to say that all animations fall under different types, we can customise each animation type to behave how we want it to.
Let’s take a look how…
Here’s how the sun.min.fill symbol looks when animated in five different ways. Using the
.symbolEffect() modifier without any options makes the animation run Indefinitely
.
While this is easy to implement, it’s usually not recommended to let animations run indefinitely
unless you have a specific, justified use case.
Image(systemName: "sun.min.fill")
.symbolEffect(.bounce)
Image(systemName: "sun.min.fill")
.symbolEffect(.breathe)
Image(systemName: "sun.min.fill")
.symbolEffect(.pulse)
Image(systemName: "sun.min.fill")
.symbolEffect(.rotate)
Image(systemName: "sun.min.fill")
.symbolEffect(.wiggle)
Examples of different indefinite SF Symbol animations using .symbolEffect().
Discrete
animations, as mentioned earlier, are an effect that run from start to finish.
Below are some of the different ways that we can achieve this effect. .symbolEffect()
has an options
parameter which takes a SymbolEffectOptions
property.
.nonRepeating
- Allows the animation to run once, and once only.
.repeat(_ count: Int?)
- Takes an integer as input, this specifies the number of times
we want the animation to repeat for.
Image(systemName: "sun.min.fill")
.symbolEffect(
.wiggle,
options: .nonRepeating
)
Image(systemName: "sun.min.fill")
.symbolEffect(
.wiggle,
options: .repeat(1)
)
Image(systemName: "sun.min.fill")
.symbolEffect(
.wiggle,
options: .repeat(3)
)
Examples of discrete SF Symbol animations using .symbolEffect().
Transition
symbol effects animate symbols in and out of visibility. While experimenting,
I didn’t notice much difference between using the .transition()
modifier and not using
it, but maybe I’m missing something?
HStack(spacing: 50) {
if isPresenting {
Image(systemName: "sun.min.fill")
.transition(.symbolEffect(.appear))
}
}
.font(.system(size: 40))
.frame(height: 50)
Button {
withAnimation {
isPresenting.toggle()
}
} label: {
Text("Animate")
}
.buttonStyle(.bordered)
Using .symbolEffect(.appear) for transition animations.
Content Transition
effects, like .replace
, animate one symbol transitioning
into another with a smooth scaling effect*.*. Using it this way seems to be most effective, when
using the symbol inside an if
statement instead of a ternary
, we don’t get
the same effect, instead you get the standard opacity animation when using
withAnimation
on it’s own.
Button {
withAnimation {
isSunny.toggle()
}
} label: {
Label("Animate", systemImage: isSunny ? "sun.max.fill" : "cloud.rain.fill")
}
.contentTransition(.symbolEffect(.replace))
.buttonStyle(.bordered)
Using .symbolEffect(.replace) for content transition animations.
You can combine different SF Symbol effects to create customised animations. Here we have used
.renderingMode(.original)
to make the heart red, we have given the
symbolEffect
options
a parameter of .repeat(3)
meaning it
will repeat 3 times, and we activate the animation using the isActive
parameter.
HStack(spacing: 50) {
Image(systemName: "heart.fill")
.renderingMode(.original)
.symbolEffect(
.breathe,
options: .repeat(3),
isActive: animateHeart
)
}
.font(.system(size: 40))
Button {
animateHeart.toggle()
} label: {
Text("Breathe")
}
.buttonStyle(.bordered)
Combining .renderingMode() and .symbolEffect() for a customised animation.
There is a lot you can do when it comes to animating SF Symbols, and I have probably only scratched the surface here. Go experiment and see what you can come up with.
Please remember that animations are best used to help enhance the users experience, and give polished professional feel to your app. Placing them everywhere can be distracting to the user, so less can be more as the saying goes.
Thanks for stopping by 🙂.