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)
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")

