Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

183 lines
5.6KB

  1. #' Animation Options
  2. #'
  3. #' Helper function to set animation and plotting options to be passed to
  4. #' [animate_plot()] and [static_plot()].
  5. #'
  6. #' @param text_family Font family for the plot text
  7. #' @param title_family Font family for the plot title
  8. #' @param text_size Font size of the plot text
  9. #' @param title_size Font size of the plot title
  10. #' @param ease_default Default aes easing function. See [tweenr::display_ease()]
  11. #' for more options.
  12. #' @param ease_other Additional aes easing options, specified as a named list.
  13. #' List entries are named with the aesthetic to which the easeing should be
  14. #' applied, consistent with [gganimate::ease_aes()].
  15. #' E.g. `list(color = "sine")`.
  16. #' @param enter Enter fading function applied to objects in the animation. See
  17. #' [gganimate::enter_exit] for a complete list of options.
  18. #' @param exit Exit fading function applied to objects in the animation. See
  19. #' [gganimate::enter_exit] for a complete list of options.
  20. #' @inheritParams gganimate::transition_states
  21. #' @export
  22. anim_options <- function(
  23. transition_length = 2,
  24. state_length = 1,
  25. ease_default = "sine-in-out",
  26. ease_other = NULL,
  27. enter = enter_fade(),
  28. exit = exit_fade(),
  29. text_family = "Fira Sans",
  30. title_family = "Fira Mono",
  31. text_size = NULL,
  32. title_size = NULL,
  33. ...
  34. ){
  35. enter_name <- rlang::quo_name(rlang::enquo(enter))
  36. exit_name <- rlang::quo_name(rlang::enquo(exit))
  37. structure(
  38. list(
  39. transition_length = transition_length,
  40. state_length = state_length,
  41. ease_default = ease_default,
  42. ease_other = ease_other,
  43. enter = setNames(list(enter), enter_name),
  44. exit = setNames(list(exit), exit_name),
  45. text_family = text_family,
  46. text_size = text_size,
  47. title_family = title_family,
  48. title_size = title_size,
  49. ...
  50. ),
  51. class = "anim_opts"
  52. )
  53. }
  54. validate_anim_opts <- function(ao, quiet = FALSE, strict = getOption("tidyexplain.strict_dots", FALSE)) {
  55. if (!inherits(ao, "anim_opts")) {
  56. rlang::warn("Use `anim_options()` to set `anim_opts`")
  57. }
  58. stopifnot(is.ggproto(ao$enter[[1]]), is.ggproto(ao$exit[[1]]))
  59. extra_names <- setdiff(names(ao), names(formals(anim_options)))
  60. if (!quiet && length(extra_names)) {
  61. extra_names <- paste0(sprintf("`%s`", extra_names), collapse = ", ")
  62. msg <- paste("Unknown animation options will be ignored:", extra_names)
  63. if (isTrue(strict)) rlang::abort(msg) else rlang::warn(msg)
  64. }
  65. invisible(ao)
  66. }
  67. #' Animates a plot
  68. #'
  69. #' @param d a processed dataset
  70. #' @param title the title of the plot
  71. #' @param anim_opts Animation options generated with [anim_options()]. Overrides
  72. #' any options set in `...`.
  73. #' @return a `gganim` object
  74. #' @examples
  75. #' NULL
  76. animate_plot <- function(
  77. d,
  78. title = "",
  79. ...,
  80. anim_opts = anim_options(...)
  81. ) {
  82. ao <- validate_anim_opts(anim_opts)
  83. ease_opts <- if (!is.null(ao$ease_other)) {
  84. ao$ease_other$default <- ao$ease_default
  85. ao$ease_other
  86. } else list(default = ao$ease_default)
  87. ao_ease_aes <- do.call(ease_aes, ease_opts)
  88. static_plot(d, title, anim_opts = ao) +
  89. transition_states(.frame, ao$transition_length, ao$state_length) +
  90. ao$enter[[1]] +
  91. ao$exit[[1]] +
  92. ao_ease_aes
  93. }
  94. #' Prints the tiles for a processed dataset statically
  95. #'
  96. #' @inheritParams animate_plot
  97. #' @inheritDotParams anim_options
  98. #'
  99. #' @return a ggplot
  100. #'
  101. #' @examples
  102. #' NULL
  103. static_plot <- function(
  104. d,
  105. title = "",
  106. ...,
  107. anim_opts = anim_options(...)
  108. ) {
  109. ao <- validate_anim_opts(anim_opts)
  110. text_size <- get_text_size(ao$text_size, default = 5)
  111. title_size <- get_title_size(ao$title_size, default = 17)
  112. if (!".alpha" %in% names(d)) d <- d %>% mutate(.alpha = 1)
  113. if (!".textcolor" %in% names(d))
  114. d <- d %>% mutate(.textcolor = choose_text_color(.color))
  115. if (".id_long" %in% names(d)) {
  116. d <- d %>% mutate(.item_id = paste(.id_long, .col, sep = "-"))
  117. } else {
  118. # tidyr
  119. d <- d %>% mutate(.item_id = .id)
  120. }
  121. ggplot(d, aes(x = .x, y = .y, fill = .color, alpha = .alpha, group = .item_id)) +
  122. geom_tile(width = 0.9, height = 0.9) +
  123. coord_equal() +
  124. geom_text(data = d %>% filter(!is.na(.val)), aes(label = .val, color = .textcolor),
  125. family = ao$text_family, size = text_size) +
  126. scale_fill_identity() +
  127. scale_color_identity() +
  128. scale_alpha_identity() +
  129. labs(title = title) +
  130. theme_void() +
  131. theme(plot.title = element_text(family = ao$title_family, hjust = 0.5, size = title_size))
  132. }
  133. #' Set Default Text Sizes for Animation Plots
  134. #'
  135. #' Sets the default text sizes for the animated and static plots produced by
  136. #' this package during the current session.
  137. #'
  138. #' @param text_size Font size of value labels inside the data frame squares
  139. #' @param title_size Font size of the function call or plot title
  140. #' @export
  141. set_font_size <- function(text_size = NULL, title_size = NULL) {
  142. old <- list()
  143. if (!is.null(text_size)) old$text_size <- set_text_size(text_size)
  144. if (!is.null(title_size)) old$title_size <- set_title_size(title_size)
  145. invisible(old)
  146. }
  147. set_text_size <- function(size) {
  148. old <- plot_settings$text_size
  149. plot_settings$text_size <- size
  150. invisible(old)
  151. }
  152. set_title_size <- function(size) {
  153. old <- plot_settings$title_size
  154. plot_settings$title_size <- size
  155. invisible(old)
  156. }
  157. get_text_size <- function(x = NULL, default = 5) {
  158. if (!is.null(x)) return(x)
  159. plot_settings$text_size %||%
  160. getFromNamespace("theme_env", "ggplot2")$current$text$size %||%
  161. default
  162. }
  163. get_title_size <- function(x = NULL, default = 17) {
  164. if (!is.null(x)) return(x)
  165. plot_settings$title_size %||%
  166. getFromNamespace("theme_env", "ggplot2")$current$plot.title$size %||%
  167. default
  168. }