😎 Give your xaringan slides some style
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

190 líneas
5.8KB

  1. `%||%` <- function(x, y) if (is.null(x)) y else x
  2. `%??%` <- function(x, y) if (!is.null(x)) y else NULL
  3. #' @title Generate lighter or darker version of a color
  4. #' @description Produces a linear blend of the color with white or black.
  5. #' @param color_hex A character string representing a hex color
  6. #' @param strength The "strength" of the blend with white or black,
  7. #' 0 low to 1 high.
  8. #' @name lighten_darken_color
  9. NULL
  10. #' @rdname lighten_darken_color
  11. #' @export
  12. lighten_color <- function(color_hex, strength = 0.7) {
  13. stopifnot(strength >= 0 && strength <= 1)
  14. color_rgb <- col2rgb(color_hex)[, 1]
  15. color_rgb <- (1 - strength) * color_rgb + strength * 255
  16. rgb(color_rgb[1], color_rgb[2], color_rgb[3], maxColorValue = 255)
  17. }
  18. #' @rdname lighten_darken_color
  19. #' @export
  20. darken_color <- function(color_hex, strength = 0.8) {
  21. stopifnot(strength >= 0 && strength <= 1)
  22. color_rgb <- col2rgb(color_hex)[, 1]
  23. color_rgb <- (1 - strength) * color_rgb
  24. rgb(color_rgb[1], color_rgb[2], color_rgb[3], maxColorValue = 255)
  25. }
  26. #' @title Add alpha to hex color
  27. #' @description Applies alpha (or opacity) to a color in hexadecimal form by
  28. #' converting opacity in the `[0, 1]` range to hex in the `[0, 255]` range
  29. #' and appending to the hex color.
  30. #' @inheritParams lighten_darken_color
  31. #' @param opacity Desired opacity of the output color
  32. #' @export
  33. apply_alpha <- function(color_hex, opacity = 0.5) {
  34. paste0(color_hex, as.hexmode(round(255 * opacity, 0)))
  35. }
  36. adjust_value_color <- function(color_hex, strength = 0.5) {
  37. color_hsv <- rgb2hsv(col2rgb(color_hex))[, 1]
  38. color_hsv["v"] <- strength
  39. hsv(color_hsv[1], color_hsv[2], color_hsv[3])
  40. }
  41. #' Choose dark or light color
  42. #'
  43. #' Takes a color input as `x` and returns either the black or white color (or
  44. #' expression) if dark or light text should be used over the input color for
  45. #' best contrast. Follows W3C Recommendations.
  46. #'
  47. #' @references <https://stackoverflow.com/a/3943023/2022615>
  48. #' @param x The background color (hex)
  49. #' @param black Text or foreground color, e.g. "#222" or
  50. #' `substitute(darken_color(x, 0.8))`, if black text provides the best contrast.
  51. #' @param white Text or foreground color or expression, e.g. "#EEE" or
  52. #' `substitute(lighten_color(x, 0.8))`, if white text provides the best contrast.
  53. #' @export
  54. choose_dark_or_light <- function(x, black = "#000000", white = "#FFFFFF") {
  55. if (is_light_color(x)) eval(black) else eval(white)
  56. }
  57. is_light_color <- function(x) {
  58. # this function returns TRUE if the given color
  59. # is light-colored and requires dark text
  60. color_rgb <- col2rgb(x)[, 1]
  61. # from https://stackoverflow.com/a/3943023/2022615
  62. color_rgb <- color_rgb / 255
  63. color_rgb[color_rgb <= 0.03928] <- color_rgb[color_rgb <= 0.03928] / 12.92
  64. color_rgb[color_rgb > 0.03928] <- ((color_rgb[color_rgb > 0.03928] + 0.055) / 1.055)^2.4
  65. lum <- t(c(0.2126, 0.7152, 0.0722)) %*% color_rgb
  66. lum[1, 1] > 0.179
  67. }
  68. requires_package <- function(pkg = "ggplot2", fn = "", required = TRUE) {
  69. raise <- if (required) stop else warning
  70. if (!requireNamespace(pkg, quietly = TRUE)) {
  71. msg <- paste0(
  72. "`",
  73. pkg,
  74. "` is ",
  75. if (required) "required " else "suggested ",
  76. if (fn != "") paste0("by ", fn, "() ")[1],
  77. "but is not installed."
  78. )
  79. raise(msg, call. = FALSE)
  80. return(invisible(FALSE))
  81. }
  82. invisible(TRUE)
  83. }
  84. #' @keywords internal
  85. call_style_xaringan <- function() {
  86. paste0(
  87. "style_xaringan(",
  88. paste(names(formals(style_xaringan)), collapse = ", "),
  89. ")"
  90. )
  91. }
  92. #' Specify Google Font
  93. #'
  94. #' Builds Google Fonts URL from family name. Extra weights are given in the
  95. #' `...` parameters. Languages can be specified in `langauges` and must one or
  96. #' more of the language codes as given by `google_language_codes()`.
  97. #'
  98. #' @examples
  99. #' google_font("Josefin Sans", "400", "400i", "600i", "700")
  100. #' google_font("Josefin Sans", languages = c("latin-ext", "vietnamese"))
  101. #' @param family Font family
  102. #' @param ... Font weights to include, example "400", "400i"
  103. #' @param languages Font languages to include (dependent on the font.) See
  104. #' [google_language_codes()].
  105. #' @export
  106. google_font <- function(family, ..., languages = NULL) {
  107. base <- "https://fonts.googleapis.com/css?family="
  108. weights <- if (length(list(...))) paste(c(...), collapse = ",")
  109. languages <- if (!is.null(languages)) paste(google_language_codes(languages), collapse = ",")
  110. structure(
  111. list(
  112. family = family,
  113. weights = weights,
  114. languages = languages,
  115. url = paste0(
  116. base,
  117. gsub(" ", "+", family),
  118. if (!is.null(weights)) paste0(":", weights),
  119. if (!is.null(languages)) paste0("&subset=", languages),
  120. "&display=swap"
  121. )
  122. ),
  123. class = "google_font"
  124. )
  125. }
  126. #' @title List Valid Google Language Codes
  127. #' @description Gives a list of valid Language Codes for Google Fonts, or
  128. #' validates that the language codes given are valid.
  129. #' @seealso [google_font()]
  130. #' @param language_codes Vector of potential Google language codes
  131. #' @export
  132. google_language_codes <- function(
  133. language_codes = c(
  134. "latin",
  135. "latin-ext",
  136. "sinhala",
  137. "greek",
  138. "hebrew",
  139. "vietnamese",
  140. "cyrillic",
  141. "cyrillic-ext",
  142. "devanagari",
  143. "arabic",
  144. "khmer",
  145. "tamil",
  146. "greek-ext",
  147. "thai",
  148. "bengali",
  149. "gujarati",
  150. "oriya",
  151. "malayalam",
  152. "gurmukhi",
  153. "kannada",
  154. "telugu",
  155. "myanmar"
  156. )) {
  157. unique(match.arg(language_codes, several.ok = TRUE))
  158. }
  159. print.google_font <- function(x) {
  160. cat(
  161. "Family: ",
  162. x$family,
  163. if (!is.null(x$weights)) paste("\nWeights:", x$weights),
  164. if (!is.null(x$languages)) paste("\nLangs: ", x$languages),
  165. "\nURL: ",
  166. x$url
  167. )
  168. }
  169. quote_elements_w_spaces <- function(x) {
  170. x <- strsplit(x, ", ?")[[1]]
  171. has_space <- grepl("\\w \\w", x)
  172. not_quoted <- grepl("^\\w.+\\w$", x)
  173. x[has_space & not_quoted] <- paste0("'", x[has_space & not_quoted], "'")
  174. paste(x, collapse = ", ")
  175. }