gganime takes a ggplot2 plot written with gganimate syntax and renders it as an
animated SVG. You build the plot the same way you would for gganimate,
then call anime() in place of animate(). The
output is a self-contained HTML widget: one vector drawing of the scene
with a timeline over its elements, played in the browser.
gganime reuses gganimate’s build machinery unchanged and only replaces the final rendering step, so the gganimate documentation remains the reference for the grammar itself.
The animations below are live. Drag the scrub bar, or use the play and pause control, to step through a frame at a time.
Your first animation
Start from a static plot.
Add a transition to animate it. transition_states()
splits the data by a discrete variable and moves the points between the
resulting states.
anim <- p +
transition_states(Species, transition_length = 2, state_length = 1)To see the animation with gganimate you would print the object or
call animate(). With gganime you call
anime():
anime(anim, nframes = 30)Transitions
gganime supports three of gganimate’s transitions.
transition_states(), above, animates between the levels
of a discrete variable.
transition_time() animates along a continuous variable,
holding it to the data range so the spacing between frames matches the
spacing between values.
aq <- ggplot(airquality, aes(Day, Temp)) +
geom_point() +
transition_time(Month)
anime(aq, nframes = 30)transition_reveal() keeps earlier data on screen and
reveals the rest along a dimension, which suits a line growing over
time.
ec <- ggplot(economics, aes(date, unemploy)) +
geom_line() +
transition_reveal(date)
anime(ec, nframes = 40)Frame labels
A transition exposes a set of per-frame variables. Insert them into the title, subtitle, or caption with glue syntax, and the text is swapped frame by frame in step with the geometry.
aq_labelled <- ggplot(airquality, aes(Day, Temp)) +
geom_point() +
transition_time(Month) +
labs(title = "Month: {frame_time}")
anime(aq_labelled, nframes = 30)Each transition provides different variables.
transition_states() gives closest_state;
transition_time() gives frame_time;
transition_reveal() gives frame_along. All
three also provide frame, nframes, and
progress.
A label may span several lines. Each line is swapped on its own, so a static first line can sit above a changing second one:
aq_two_line <- ggplot(airquality, aes(Day, Temp)) +
geom_point() +
transition_time(Month) +
labs(title = "Temperature by day\nMonth: {frame_time}")
anime(aq_two_line, nframes = 30)The number of lines has to be the same in every frame. The text layout is taken from the first frame, so a label that gains or loses a line partway through is held at its first-frame text with a warning.
Easing, entering, and exiting
ease_aes() sets how an aesthetic moves between values
across a transition. The default is linear; naming an aesthetic gives it
its own easing.
enter_*() and exit_*() control how data
that appears or leaves is drawn, so its entrance and exit can be
animated.
anim_species <- ggplot(iris, aes(Petal.Width, Petal.Length)) +
geom_point(aes(colour = Species), size = 2) +
transition_states(Species, transition_length = 2, state_length = 1)
anime(anim_species + enter_fade() + exit_shrink(), nframes = 30)Each family animates a different attribute: fade the paint opacity, grow and shrink the size, drift, fly and manual the position, recolour the paint. All of them work with the four supported geoms.
Two behaviours below come from gganimate itself and appear in its
gifs as well. enter_recolour() and
exit_recolour() set colour and
fill together, and setting the aesthetic a geom does not
paint makes tweenr coerce a logical column, which warns; pass
NA for that aesthetic, as in
enter_recolour(colour = "white", fill = NA) for the default
point shape. enter_grow() and exit_shrink() do
not change the geometry of a geom_ribbon() or
geom_area() layer, so a ribbon that arrives is drawn at its
full shape.
Several layers at once
Layers are animated independently, so you can stack them the way you would in a static plot. Each layer keeps its own elements even when two layers draw the same kind of shape.
aq_layers <- ggplot(
airquality[airquality$Month %in% c(5, 6, 7), ],
aes(Day, Temp)
) +
geom_area(fill = "#9ecae1") +
geom_line(linewidth = 1, colour = "#08519c") +
geom_point(size = 2, colour = "#a50f15") +
labs(title = "Month {closest_state}") +
transition_states(Month, transition_length = 2, state_length = 1)
anime(aq_layers, nframes = 30)A layer that does not use the transition variable is drawn once and left in place, which is how you add a fixed reference against the animated data.
Leaving a trail
shadow_mark() keeps the marks from earlier frames on
screen behind the current one, so a scatter builds up as it
advances.
aq_shadow <- ggplot(airquality, aes(Day, Temp)) +
geom_point() +
transition_time(Month) +
shadow_mark(colour = "grey70") +
labs(title = "Month: {frame_time}")
anime(aq_shadow, nframes = 30)shadow_trail() keeps every nth frame instead, spacing
the marks out in time rather than showing all of them.
distance sets the spacing as a fraction of the animation,
and max_frames caps how many marks are kept, so the oldest
one drops away as a new one is added.
aq_trail <- ggplot(airquality, aes(Day, Temp)) +
geom_point() +
transition_time(Month) +
shadow_trail(distance = 0.1, max_frames = 5, colour = "grey70") +
labs(title = "Month: {frame_time}")
anime(aq_trail, nframes = 30)Controlling the render
gganime fixes the frame count and playback speed when you call
anime(), the same way gganimate does at
animate():
-
nframessets how many frames the animation is sampled at (default100). -
fpssets the playback speed in frames per second (default10), or givedurationin seconds to set the speed from the total length. -
looprepeats the animation:TRUE,FALSE, or a number of iterations. -
controlsshows or hides the play and scrub bar. -
widthandheightfix the widget size in pixels; leaving themNULLlets it fill its container. -
precisionrounds the animated coordinates, which trims the file size.
anime(anim, nframes = 50, duration = 4, loop = FALSE)Saving and embedding
anime() returns an htmlwidget, so it prints in the
RStudio Viewer, knits into R Markdown and Quarto documents, and saves to
a standalone HTML file with htmlwidgets::saveWidget():
htmlwidgets::saveWidget(anime(anim), "iris.html")Loading gganime also makes a bare gganimate plot print through
anime() at the console, so printing anim gives
the widget without an explicit call. Set
options(gganime.autoprint = FALSE) to keep gganimate’s own
output.
In Shiny, pair renderGganime() in the server with
gganimeOutput() in the UI.
Supported features
- Transitions:
transition_states(),transition_time(),transition_reveal(). - Geoms: points, lines and paths, bars and columns, areas and ribbons.
- Point shapes: any pch R draws from a single shape – circles, squares, triangles, diamonds – animates its size and outline width. The shapes drawn from several parts (pch 3, 4, and 7 to 14) hold their size.
- Several layers in one plot, including two of the same kind, and a static layer beside an animated one.
- Facets:
facet_wrap()andfacet_grid(), with fixed or free scales. - Coords:
coord_cartesian(),coord_fixed()/coord_equal(), andcoord_flip(). -
enter_*()andexit_*(),ease_aes(), and per-frame labels in the title, subtitle, and caption. -
shadow_mark()andshadow_trail().
Anything else stops with a message naming an alternative. Current
limits include non-linear coordinate systems
(coord_polar(), coord_radial(),
coord_transform(), coord_sf()),
shadow_wake(), and view_*() other than
view_static().