henryjean
henryjean

Reputation: 102

Fix blurry/overlapping text when using gganimate

I'm having trouble creating high resolution files when using gganimate. The text in the charts comes out blurry, almost as if the text is being written for every new frame in the .gif.

Example of blurry chart text

Is there a simple solution to this problem? I tried fiddling with the ani.options(), but haven't had any luck there either.

Example data and code:

value <- sample(0:30, 300, replace = TRUE)
year <- rep(c(2000, 2001, 2002), 100)

df <- as.data.frame(cbind(value, year))

library(gganimate)
library(tidyverse)

df <- df %>% group_by(year) %>% mutate(avg.value = mean(value))    

p <- df %>% 
   ggplot(aes(x = value)) + 
   geom_histogram(position = 'identity', color = "white") + 
   geom_segment(aes(xend = avg.value, x = avg.value, y = 0, yend = -.5), 
   color = "red", size = 2.5) +
   transition_states(as.factor(year), transition_length = 2, state_length 
   = 1, wrap = TRUE) + 
   annotate("text", x = df$avg.value, y = -1, label = "Average") + 
   labs(x = " ", 
   y = "", 
   title = "Example chart", 
   subtitle = "Don't it look blurry?")

animate(p, nframes = 100, renderer = gifski_renderer("example.gif"))

Upvotes: 3

Views: 1012

Answers (1)

pogibas
pogibas

Reputation: 28369

To annotate (or geom_text in my code) you're submitting multiple same avg.value values. When for yeach year you need only one you're adding hundred values. This results in hundred "Average" plotted on each other.
Solution is to submit different data to geom_text (ie, df2) that contains only 3 rows (one entry for each year).

Code:

library(gganimate)
library(tidyverse)
value <- sample(0:30, 300, replace = TRUE)
year <- rep(c(2000, 2001, 2002), 100)

df1 <- as.data.frame(cbind(value, year))
df1 <- df1 %>% group_by(year) %>% mutate(avg.value = mean(value))    
df2 <- df1 %>% group_by(year) %>% summarize(avg.value = head(avg.value, 1))    

r1 <- ggplot(df1) + 
   geom_histogram(aes(value), position = "identity", color = "white") + 
   geom_segment(aes(x = avg.value, xend = avg.value, y = 0, yend = -0.5), 
                color = "red", size = 2.5) +
   geom_text(aes(avg.value, -1, label = "Average"), df2) + 
   transition_states(as.factor(year), 2, 1) + 
   labs(title = "Example chart", 
        subtitle = "No more blur",
        x = NULL, 
        y = NULL)
animate(r1, nframes = 100, renderer = gifski_renderer("example.gif"))

Upvotes: 2

Related Questions