Overlay synced gif on `gganimate` plot

35 views Asked by At

Is there a (better) way to overlay a gif onto a gganimate plot such that the timing of both are synced? For example, if I wanted to show real time reaction data as a short clip unfolds, I'd like the data in the plot and the displayed movie/gif to be in sync. Here's a minimum reproducible example of what I'd like.

library(tidyverse)
library(fs)
library(magick)
library(gganimate)

img <- image_read("https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExOGx1dTVqbW4wdTZvaWF4NHQ5am9qMTl3ZTl6MHR3c2g1ODdiOWMwMCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/i1d0SUDlsF5oxkZhV2/giphy.gif")

imgr <- img |> 
  image_resize("x200")

img2 <- imgr[1:100] |> 
  image_animate(fps = 25)

data <- tibble(
  time = seq(1, 100),
  rating = rnorm(100, 2, 1)
)

data |> 
  ggplot(aes(x=time, y=rating)) +
  geom_line() +
  geom_point() +
  theme_minimal() +
  ylab("Enjoyment Rating") +
  coord_cartesian(ylim = c(0, 8), xlim = c(0,100)) + 
  annotation_raster(img2[2], xmin = 35, xmax = 65, ymin = 5, ymax = 8, interpolate = TRUE)

p1

This is fine for a single frame of the gif, but how would I get this animated in sync?

p <- data |> 
  ggplot(aes(x=time, y=rating)) +
  geom_line() +
  geom_point() +
  theme_minimal() +
  ylab("Enjoyment Rating") +
  coord_cartesian(ylim = c(0, 8), xlim = c(0,100)) + 
  # annotation_raster(img2[2], xmin = 35, xmax = 65, ymin = 5, ymax = 8, interpolate = TRUE)
  transition_reveal(time)

I can always do something like the following, but it feels less than ideal.

for (i in 1:100) {
  this_data <- data[1:i,]
  p <- this_data |> 
    ggplot(aes(x=time, y=rating)) +
    geom_line() +
    # geom_point() +
    theme_bw() +
    ylab("Enjoyment Rating") +
    coord_cartesian(ylim = c(0, 8), xlim = c(0,100)) + 
    annotation_raster(img2[i], xmin = 35, xmax = 65, ymin = 5, ymax = 8, interpolate = TRUE)
  # transition_reveal(time)
  
  snum <- sprintf( "%03d", i)
  ggsave(
    filename = str_glue("plot/{snum}_p.png"),
    plot = p,
    width = 400, height = 250, units = "px", 
    dpi = 150)
}

files <- dir_ls("plot/")
p2 <- image_animate(image_read(files), fps = 25)
image_write(p2, path = "p2.gif")

p2

0

There are 0 answers