Skip to content

animate and ggsave interpret theme spacing differently #505

@bbcuffer

Description

@bbcuffer

The images saved by animate have different spacing to those saved by ggsave: particularly the vertical space surrounding titles/captions.

Dotplot with title, subtitle and caption. Two versions of the same chart are overlaid to show alignment. One version is produced with ggsave, the other with gganimate's animate. The vertical spacing is different in each version

Here's the code that generates the image above. It

  • sets up a basic plot
  • saves it two ways: once using ggsave and once using animate.
  • collates the two images.

Fwiw, I don't think it's a ragg thing: I've had similar issues when saving with svglite. Nor do I think it's a ggsave thing, since it doesn't matter whether I open a graphics device, print the image and then close it or use ggsave to do that work.

library(ggplot2)
library(gganimate)
library(magick)

# The example data:
# Ten points: when state==1, they count up to 10. When state==2, they count down

df <- data.frame(
  x = rep(1:10, 2),
  y = c(1:10, 10:1),
  state = rep(1:2, c(10, 10))
)

# set up the basics of a plot.
base_plot <- ggplot(df, aes(x = x, y = y, group = x)) +
  labs(title = "gganimate v ggsave", subtitle = "Subtitle here", caption = "Caption at bottom") +
  theme_minimal(base_size = 18) +
  scale_x_continuous(limits = c(0, 10)) +
  scale_y_continuous(limits = c(0, 10))


# Version 1: save the images directly using ggsave
ggsave_fn <- ggsave(
  plot = (base_plot %+% subset(df, state == 1)) + geom_point(),
  file = tempfile(fileext = ".png"),
  device = ragg::agg_png,
  width = 5, height = 5, bg = "white",
)


# Version 2: save the images via gganimate.
# first, set up an animation to transition from counting up to counting down
pt_anim <- base_plot +
  labs(title = "gganimate v") +
  geom_point(colour = "red") +
  theme(
    text = element_text(colour = "red"),
    axis.text = element_text(colour = "red"),
    panel.grid = element_line(colour = "pink")
  ) +
  transition_states(state, wrap = FALSE)

# and save one frame per state
gganimate_fns <- animate(pt_anim,
  renderer = \(frames, fps) frames,
  nframes = 2,
  fps = 1,
  device = "ragg_png",
  width = 5,
  height = 5,
  units = "in", res = 300,
  background = NA
)

# Compare the two versions
foreground <- image_read(gganimate_fns[1])
# overlaying the gganimate version on top of the ggsave version
output_fn <- image_read(ggsave_fn) |>
  image_composite(foreground) |>
  image_write(tempfile(pattern = "comparison", fileext = ".png"))

# Produces the chart shown above
browseURL(output_fn)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions