And demonstrates usage with the tidyr gather/spread animators. In essence, user-facing functions take an argument `anim_opts = anim_options()` as a last argument (after ... if applicable). These options should be passed through to lower level functions and should be given to `animate_plot()` and `static_plot()`. This implementation actually doesn't break previous functions, but the join and set families will need to be updated to match.pkg-add-anim-opts-fixed
| # Generated by roxygen2: do not edit by hand | # Generated by roxygen2: do not edit by hand | ||||
| export("%>%") | export("%>%") | ||||
| export(anim_options) | |||||
| export(animate_anti_join) | export(animate_anti_join) | ||||
| export(animate_full_join) | export(animate_full_join) | ||||
| export(animate_gather) | export(animate_gather) |
| #' @param w a data_frame in the wide format | #' @param w a data_frame in the wide format | ||||
| #' @param key the key | #' @param key the key | ||||
| #' @param value the value | #' @param value the value | ||||
| #' @param ... further arguments passed to gather, static_plot, or animate_plot | |||||
| #' @param export the export type, either gif, first or last. The latter two | |||||
| #' export ggplots of the first/last state of the gather function | |||||
| #' @param ... further arguments passed to [tidyr::gather()], [process_wide()], | |||||
| #' or [process_long()] | |||||
| #' @param detailed boolean value if the animation should show one step for each | #' @param detailed boolean value if the animation should show one step for each | ||||
| #' key value | |||||
| #' key value | |||||
| #' @inheritParams animate_join | |||||
| #' @inheritParams anim_options | |||||
| #' | #' | ||||
| #' @return a gif or a ggplot | #' @return a gif or a ggplot | ||||
| #' @export | #' @export | ||||
| #' # if you want to have a less detailed animation, you can also use | #' # if you want to have a less detailed animation, you can also use | ||||
| #' animate_gather(wide, "person", "sales", -year, export = "gif", detailed = FALSE) | #' animate_gather(wide, "person", "sales", -year, export = "gif", detailed = FALSE) | ||||
| #' } | #' } | ||||
| animate_gather <- function(w, key, value, ..., export = "gif", detailed = TRUE) { | |||||
| animate_gather <- function(w, key, value, ..., export = "gif", detailed = TRUE, anim_opts = anim_options()) { | |||||
| lhs <- w | lhs <- w | ||||
| rhs <- tidyr::gather(w, !!key, !!value, ...) | rhs <- tidyr::gather(w, !!key, !!value, ...) | ||||
| rhs_proc <- process_long(rhs, ids, key, value, ...) | rhs_proc <- process_long(rhs, ids, key, value, ...) | ||||
| gather_spread(lhs_proc, rhs_proc, sequence = sequence, key_values = key_values, | gather_spread(lhs_proc, rhs_proc, sequence = sequence, key_values = key_values, | ||||
| export = export, detailed = detailed, ...) | |||||
| export = export, detailed = detailed, ..., anim_opts = anim_opts) | |||||
| } | } | ||||
| #' Animates the spread function | #' Animates the spread function | ||||
| #' | #' | ||||
| #' @param l a data_frame in the long/tidy format | #' @param l a data_frame in the long/tidy format | ||||
| #' @param key the key | |||||
| #' @param value the values | |||||
| #' @param export the export type, either gif, first or last. The latter two | |||||
| #' export ggplots of the first/last state of the spread function | |||||
| #' @param detailed boolean value if the animation should show one step for each | |||||
| #' key value | |||||
| #' @param ... further arguments passed to static_plot | |||||
| #' @param ... further arguments passed to [process_long] or [process_wide] | |||||
| #' @inheritParams animate_gather | |||||
| #' @inheritParams animate_join | |||||
| #' @inheritParams anim_options | |||||
| #' | #' | ||||
| #' @return a ggplot or a gif | #' @return a ggplot or a gif | ||||
| #' @export | #' @export | ||||
| #' # if you want to have a less detailed animation, you can also use | #' # if you want to have a less detailed animation, you can also use | ||||
| #' animate_spread(long, key = "person", value = "sales", export = "gif", detailed = FALSE) | #' animate_spread(long, key = "person", value = "sales", export = "gif", detailed = FALSE) | ||||
| #' } | #' } | ||||
| animate_spread <- function(l, key, value, export = "gif", detailed = TRUE, ...) { | |||||
| animate_spread <- function(l, key, value, export = "gif", detailed = TRUE, ..., anim_opts = anim_options()) { | |||||
| lhs <- l | lhs <- l | ||||
| rhs <- tidyr::spread(l, key = key, value = value) | rhs <- tidyr::spread(l, key = key, value = value) | ||||
| rhs_proc <- process_wide(rhs, ids, key, value, ...) | rhs_proc <- process_wide(rhs, ids, key, value, ...) | ||||
| key_values <- lhs %>% pull(key) %>% unique() | key_values <- lhs %>% pull(key) %>% unique() | ||||
| gather_spread(lhs_proc, rhs_proc, sequence, key_values, export, detailed, ...) | |||||
| gather_spread(lhs_proc, rhs_proc, sequence, key_values, export, detailed, ..., anim_opts = anim_opts) | |||||
| } | } |
| #' Animates a plot | |||||
| #' Animation Options | |||||
| #' | #' | ||||
| #' @param d a preprocessed dataset | |||||
| #' @param title the plot title | |||||
| #' @param transition_length see transition_states | |||||
| #' @param state_length see transition_states | |||||
| #' @param ... further arguments passed to static_plot | |||||
| #' Helper function to set animation and plotting options to be passed to | |||||
| #' [animate_plot()] and [static_plot()]. | |||||
| #' | #' | ||||
| #' @return a gif | |||||
| #' @param text_family Font family for the plot text | |||||
| #' @param title_family Font family for the plot title | |||||
| #' @param text_size Font size of the plot text | |||||
| #' @param title_size Font size of the plot title | |||||
| #' @param ease_default Default aes easing function. See [tweenr::display_ease] | |||||
| #' for more options. | |||||
| #' @param ease_other Additional aes easing options, named with aesthetic to | |||||
| #' which the easeing should be applied, consistent with [gganimate::ease_aes()]. | |||||
| #' @param enter_exit Enter/exit fading functions applied to objects in the animation. | |||||
| #' See [gganimate::enter_exit] for a complete list of options. | |||||
| #' @inheritParams gganimate::transition_states | |||||
| #' @export | |||||
| anim_options <- function( | |||||
| transition_length = 2, | |||||
| state_length = 1, | |||||
| ease_default = "sine-in-out", | |||||
| ease_other = NULL, | |||||
| enter_ = enter_fade(), | |||||
| exit_ = exit_fade(), | |||||
| text_family = "Fira Sans", | |||||
| title_family = "Fira Mono", | |||||
| text_size = NULL, | |||||
| title_size = NULL, | |||||
| ... | |||||
| ){ | |||||
| structure( | |||||
| list( | |||||
| transition_length = transition_length, | |||||
| state_length = state_length, | |||||
| ease_default = ease_default, | |||||
| ease_other = ease_other, | |||||
| enter_ = enter_, | |||||
| exit_ = exit_, | |||||
| text_family = text_family, | |||||
| text_size = text_size, | |||||
| title_family = title_family, | |||||
| title_size = title_size, | |||||
| ... | |||||
| ), | |||||
| class = "anim_opts" | |||||
| ) | |||||
| } | |||||
| #' Animates a plot | |||||
| #' | #' | ||||
| #' @param d a processed dataset | |||||
| #' @param title the title of the plot | |||||
| #' @param anim_opts Animation options generated with [anim_options()]. Overrides | |||||
| #' any options set in `...`. | |||||
| #' @return a `gganim` object | |||||
| #' @examples | #' @examples | ||||
| #' NULL | #' NULL | ||||
| animate_plot <- function(d, title = "", transition_length = 2, state_length = 1, ...) { | |||||
| static_plot(d, title, ...) + | |||||
| transition_states(.frame, transition_length, state_length) + | |||||
| enter_fade() + | |||||
| exit_fade() + | |||||
| ease_aes("sine-in-out") | |||||
| animate_plot <- function( | |||||
| d, | |||||
| title = "", | |||||
| ..., | |||||
| anim_opts = anim_options(...) | |||||
| ) { | |||||
| ao <- anim_opts | |||||
| ease_opts <- if (!is.null(ao$ease_other)) { | |||||
| ao$ease_other$default <- ao$ease_default | |||||
| ao$ease_other | |||||
| } else list(default = ao$ease_default) | |||||
| ao_ease_aes <- do.call(ease_aes, ease_opts) | |||||
| static_plot(d, title, ao$text_family, ao$title_family, ao$text_size, ao$title_size) + | |||||
| transition_states(.frame, ao$transition_length, ao$state_length) + | |||||
| ao$enter_ + | |||||
| ao$exit_ + | |||||
| ao_ease_aes | |||||
| } | } | ||||
| #' Prints the tiles for a processed dataset statically | #' Prints the tiles for a processed dataset statically | ||||
| #' | #' | ||||
| #' @param d a processed dataset | |||||
| #' @param title the title of the plot | |||||
| #' @param text_family the font for the text | |||||
| #' @param title_family the font for the title | |||||
| #' @param text_size the size of the text | |||||
| #' @param title_size the size of the title | |||||
| #' @param ... further arguments | |||||
| #' @inheritParams animate_plot | |||||
| #' @inheritDotParams anim_options | |||||
| #' | #' | ||||
| #' @return a ggplot | #' @return a ggplot | ||||
| #' | #' | ||||
| static_plot <- function( | static_plot <- function( | ||||
| d, | d, | ||||
| title = "", | title = "", | ||||
| text_family = "Fira Sans", title_family = "Fira Mono", | |||||
| text_size = NULL, title_size = NULL, | |||||
| ... | |||||
| ..., | |||||
| anim_opts = anim_options(...) | |||||
| ) { | ) { | ||||
| text_size <- get_text_size(text_size, default = 5) | |||||
| title_size <- get_title_size(title_size, default = 17) | |||||
| ao <- anim_opts | |||||
| text_size <- get_text_size(ao$text_size, default = 5) | |||||
| title_size <- get_title_size(ao$title_size, default = 17) | |||||
| if (!".alpha" %in% names(d)) d <- d %>% mutate(.alpha = 1) | if (!".alpha" %in% names(d)) d <- d %>% mutate(.alpha = 1) | ||||
| if (!".textcolor" %in% names(d)) | if (!".textcolor" %in% names(d)) | ||||
| geom_tile(width = 0.9, height = 0.9) + | geom_tile(width = 0.9, height = 0.9) + | ||||
| coord_equal() + | coord_equal() + | ||||
| geom_text(data = d %>% filter(!is.na(.val)), aes(label = .val, color = .textcolor), | geom_text(data = d %>% filter(!is.na(.val)), aes(label = .val, color = .textcolor), | ||||
| family = text_family, size = text_size) + | |||||
| family = ao$text_family, size = text_size) + | |||||
| scale_fill_identity() + | scale_fill_identity() + | ||||
| scale_color_identity() + | scale_color_identity() + | ||||
| scale_alpha_identity() + | scale_alpha_identity() + | ||||
| labs(title = title) + | labs(title = title) + | ||||
| theme_void() + | theme_void() + | ||||
| theme(plot.title = element_text(family = title_family, hjust = 0.5, size = title_size)) | |||||
| theme(plot.title = element_text(family = ao$title_family, hjust = 0.5, size = title_size)) | |||||
| } | } | ||||
| #' Set Default Text Sizes for Animation Plots | #' Set Default Text Sizes for Animation Plots |
| #' | #' | ||||
| #' @examples | #' @examples | ||||
| #' NULL | #' NULL | ||||
| gather_spread <- function(lhs, rhs, sequence, key_values, export, detailed, ...) { | |||||
| gather_spread <- function(lhs, rhs, sequence, key_values, export, detailed, ..., anim_opts = anim_options()) { | |||||
| # lhs is the one state of the df | # lhs is the one state of the df | ||||
| # rhs is the target state | # rhs is the target state | ||||
| labels = frame_labels)) | labels = frame_labels)) | ||||
| if (export == "gif") { | if (export == "gif") { | ||||
| animate_plot(anim_df, title = title_string, transition_length = tl, state_length = sl) #, ...) | |||||
| animate_plot(anim_df, title = title_string, anim_opts = anim_opts) | |||||
| } else if (export == "first") { | } else if (export == "first") { | ||||
| static_plot(state_start) #.... | |||||
| static_plot(state_start, anim_opts = anim_opts) #.... | |||||
| } else if (export == "last") { | } else if (export == "last") { | ||||
| static_plot(state_end) #.... | |||||
| static_plot(state_end, anim_opts = anim_opts) #.... | |||||
| } | } | ||||
| # open issues: ... doesnt work properly. | # open issues: ... doesnt work properly. |
| % Generated by roxygen2: do not edit by hand | |||||
| % Please edit documentation in R/plot_helpers.R | |||||
| \name{anim_options} | |||||
| \alias{anim_options} | |||||
| \title{Animation Options} | |||||
| \usage{ | |||||
| anim_options(transition_length = 2, state_length = 1, | |||||
| ease_default = "sine-in-out", ease_other = NULL, | |||||
| enter_ = enter_fade(), exit_ = exit_fade(), | |||||
| text_family = "Fira Sans", title_family = "Fira Mono", | |||||
| text_size = NULL, title_size = NULL, ...) | |||||
| } | |||||
| \arguments{ | |||||
| \item{transition_length}{The relative length of the transition. Will be | |||||
| recycled to match the number of states in the data} | |||||
| \item{state_length}{The relative length of the pause at the states. Will be | |||||
| recycled to match the number of states in the data} | |||||
| \item{ease_default}{Default aes easing function. See \link[tweenr:display_ease]{tweenr::display_ease} | |||||
| for more options.} | |||||
| \item{ease_other}{Additional aes easing options, named with aesthetic to | |||||
| which the easeing should be applied, consistent with \code{\link[gganimate:ease_aes]{gganimate::ease_aes()}}.} | |||||
| \item{text_family}{Font family for the plot text} | |||||
| \item{title_family}{Font family for the plot title} | |||||
| \item{text_size}{Font size of the plot text} | |||||
| \item{title_size}{Font size of the plot title} | |||||
| \item{enter_exit}{Enter/exit fading functions applied to objects in the animation. | |||||
| See \link[gganimate:enter_exit]{gganimate::enter_exit} for a complete list of options.} | |||||
| } | |||||
| \description{ | |||||
| Helper function to set animation and plotting options to be passed to | |||||
| \code{\link[=animate_plot]{animate_plot()}} and \code{\link[=static_plot]{static_plot()}}. | |||||
| } |
| \alias{animate_gather} | \alias{animate_gather} | ||||
| \title{Animates the gather function} | \title{Animates the gather function} | ||||
| \usage{ | \usage{ | ||||
| animate_gather(w, key, value, ..., export = "gif", detailed = TRUE) | |||||
| animate_gather(w, key, value, ..., export = "gif", detailed = TRUE, | |||||
| anim_opts = anim_options()) | |||||
| } | } | ||||
| \arguments{ | \arguments{ | ||||
| \item{w}{a data_frame in the wide format} | \item{w}{a data_frame in the wide format} | ||||
| \item{value}{the value} | \item{value}{the value} | ||||
| \item{...}{further arguments passed to gather, static_plot, or animate_plot} | |||||
| \item{...}{further arguments passed to \code{\link[tidyr:gather]{tidyr::gather()}}, \code{\link[=process_wide]{process_wide()}}, | |||||
| or \code{\link[=process_long]{process_long()}}} | |||||
| \item{export}{the export type, either gif, first or last. The latter two | \item{export}{the export type, either gif, first or last. The latter two | ||||
| export ggplots of the first/last state of the gather function} | |||||
| export ggplots of the first/last state of the join} | |||||
| \item{detailed}{boolean value if the animation should show one step for each | \item{detailed}{boolean value if the animation should show one step for each | ||||
| key value} | key value} |
| \alias{animate_plot} | \alias{animate_plot} | ||||
| \title{Animates a plot} | \title{Animates a plot} | ||||
| \usage{ | \usage{ | ||||
| animate_plot(d, title = "", transition_length = 2, state_length = 1, | |||||
| ...) | |||||
| animate_plot(d, title = "", ..., anim_opts = anim_options(...)) | |||||
| } | } | ||||
| \arguments{ | \arguments{ | ||||
| \item{d}{a preprocessed dataset} | |||||
| \item{d}{a processed dataset} | |||||
| \item{title}{the plot title} | |||||
| \item{title}{the title of the plot} | |||||
| \item{transition_length}{see transition_states} | |||||
| \item{state_length}{see transition_states} | |||||
| \item{...}{further arguments passed to static_plot} | |||||
| \item{anim_opts}{Animation options generated with \code{\link[=anim_options]{anim_options()}}. Overrides | |||||
| any options set in \code{...}.} | |||||
| } | } | ||||
| \value{ | \value{ | ||||
| a gif | |||||
| a \code{gganim} object | |||||
| } | } | ||||
| \description{ | \description{ | ||||
| Animates a plot | Animates a plot |
| \alias{animate_spread} | \alias{animate_spread} | ||||
| \title{Animates the spread function} | \title{Animates the spread function} | ||||
| \usage{ | \usage{ | ||||
| animate_spread(l, key, value, export = "gif", detailed = TRUE, ...) | |||||
| animate_spread(l, key, value, export = "gif", detailed = TRUE, ..., | |||||
| anim_opts = anim_options()) | |||||
| } | } | ||||
| \arguments{ | \arguments{ | ||||
| \item{l}{a data_frame in the long/tidy format} | \item{l}{a data_frame in the long/tidy format} | ||||
| \item{key}{the key} | \item{key}{the key} | ||||
| \item{value}{the values} | |||||
| \item{value}{the value} | |||||
| \item{export}{the export type, either gif, first or last. The latter two | \item{export}{the export type, either gif, first or last. The latter two | ||||
| export ggplots of the first/last state of the spread function} | |||||
| export ggplots of the first/last state of the join} | |||||
| \item{detailed}{boolean value if the animation should show one step for each | \item{detailed}{boolean value if the animation should show one step for each | ||||
| key value} | key value} | ||||
| \item{...}{further arguments passed to static_plot} | |||||
| \item{...}{further arguments passed to \link{process_long} or \link{process_wide}} | |||||
| } | } | ||||
| \value{ | \value{ | ||||
| a ggplot or a gif | a ggplot or a gif |
| \alias{gather_spread} | \alias{gather_spread} | ||||
| \title{Animates a gather or spread function} | \title{Animates a gather or spread function} | ||||
| \usage{ | \usage{ | ||||
| gather_spread(lhs, rhs, sequence, key_values, export, detailed, ...) | |||||
| gather_spread(lhs, rhs, sequence, key_values, export, detailed, ..., | |||||
| anim_opts = anim_options()) | |||||
| } | } | ||||
| \arguments{ | \arguments{ | ||||
| \item{lhs}{the (processed) dataset on the left-side} | \item{lhs}{the (processed) dataset on the left-side} |
| \alias{static_plot} | \alias{static_plot} | ||||
| \title{Prints the tiles for a processed dataset statically} | \title{Prints the tiles for a processed dataset statically} | ||||
| \usage{ | \usage{ | ||||
| static_plot(d, title = "", text_family = "Fira Sans", | |||||
| title_family = "Fira Mono", text_size = NULL, title_size = NULL, | |||||
| ...) | |||||
| static_plot(d, title = "", ..., anim_opts = anim_options(...)) | |||||
| } | } | ||||
| \arguments{ | \arguments{ | ||||
| \item{d}{a processed dataset} | \item{d}{a processed dataset} | ||||
| \item{title}{the title of the plot} | \item{title}{the title of the plot} | ||||
| \item{text_family}{the font for the text} | |||||
| \item{...}{Arguments passed on to \code{anim_options} | |||||
| \describe{ | |||||
| \item{text_family}{Font family for the plot text} | |||||
| \item{title_family}{Font family for the plot title} | |||||
| \item{text_size}{Font size of the plot text} | |||||
| \item{title_size}{Font size of the plot title} | |||||
| \item{ease_default}{Default aes easing function. See \link[tweenr:display_ease]{tweenr::display_ease} | |||||
| for more options.} | |||||
| \item{ease_other}{Additional aes easing options, named with aesthetic to | |||||
| which the easeing should be applied, consistent with \code{\link[gganimate:ease_aes]{gganimate::ease_aes()}}.} | |||||
| \item{transition_length}{The relative length of the transition. Will be | |||||
| recycled to match the number of states in the data} | |||||
| \item{state_length}{The relative length of the pause at the states. Will be | |||||
| recycled to match the number of states in the data} | |||||
| }} | |||||
| \item{title_family}{the font for the title} | |||||
| \item{text_size}{the size of the text} | |||||
| \item{title_size}{the size of the title} | |||||
| \item{...}{further arguments} | |||||
| \item{anim_opts}{Animation options generated with \code{\link[=anim_options]{anim_options()}}. Overrides | |||||
| any options set in \code{...}.} | |||||
| } | } | ||||
| \value{ | \value{ | ||||
| a ggplot | a ggplot |