diff --git a/NEWS.md b/NEWS.md index cef11914..3b9ce2d4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -153,6 +153,10 @@ Theme fixes: and drawing them as standalone bars. This is useful for Likert plots, where you want to show a neutral categories (e.g., "Unsure") apart from the diverging stack. Thanks to @strengejacke for the suggestion. +- `type_text()` (and `type = "text"`) gains a `labeller` argument that is passed + to `tinylabel()` for formatting the text labels. This is useful for ensuring + that text annotations match a formatted axis, e.g. `labeller = "%"` to display + the labels as percentages. (#620 @grantmcdermott) ### Bug fixes diff --git a/R/type_text.R b/R/type_text.R index f0774be9..fd7c8af6 100644 --- a/R/type_text.R +++ b/R/type_text.R @@ -6,6 +6,11 @@ #' @param labels Character vector of length `1` or the same length as the #' number of `x`,`y` coordinates. If left as `NULL`, then the labels will #' automatically inherit the corresponding `y` values. See Examples. +#' @param labeller A formatting function (or convenience string) passed to +#' [`tinylabel`] for formatting the `labels`. Useful for ensuring that the +#' text labels match the formatting of an axis, e.g. `labeller = "%"` to +#' display the labels as percentages. Default is `NULL`, i.e. no formatting. +#' See Examples. #' @param family The name of a font family. Default of `NULL` means that the #' family will be the same as the main plot text, following #' \code{\link[graphics]{par}}. Note that if a `family` argument is provided, @@ -53,9 +58,15 @@ #' ) #' ) #' +#' # use `labeller` to format the labels, e.g. to match a formatted axis +#' d = data.frame(x = c("A", "B"), y = c(0.5, 0.8)) +#' tinyplot(y ~ x, data = d, type = "bar", ylim = c(0, 1), yaxl = "%") +#' tinyplot_add(type = type_text(labeller = "%", adj = c(0.5, -0.5))) +#' #' @export type_text = function( labels = NULL, + labeller = NULL, adj = NULL, pos = NULL, offset = 0.5, @@ -77,20 +88,20 @@ type_text = function( xpd = xpd, srt = srt ), - data = data_text(labels = labels, clim = clim), + data = data_text(labels = labels, labeller = labeller, clim = clim), name = "text" ) class(out) = "tinyplot_type" return(out) } -data_text = function(labels = NULL, clim = c(0.5, 2.5)) { +data_text = function(labels = NULL, labeller = NULL, clim = c(0.5, 2.5)) { fun = function(settings, ...) { env2env(settings, environment(), "datapoints") - + # Store clim for bubble() function settings$clim = clim - + if (is.null(labels)) { labels = datapoints$y } @@ -98,6 +109,9 @@ data_text = function(labels = NULL, clim = c(0.5, 2.5)) { msg = sprintf("`labels` must be of length 1 or %s.", nrow(datapoints)) stop(msg, call. = FALSE) } + if (!is.null(labeller)) { + labels = tinylabel(labels, labeller) + } datapoints$labels = labels if (is.factor(datapoints$x)) { datapoints$x = as.numeric(datapoints$x) diff --git a/inst/tinytest/_tinysnapshot/text_labeller_percent.svg b/inst/tinytest/_tinysnapshot/text_labeller_percent.svg new file mode 100644 index 00000000..c8822428 --- /dev/null +++ b/inst/tinytest/_tinysnapshot/text_labeller_percent.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + +x +y +A +B + + + + + + + +0% +20% +40% +60% +80% +100% + + + + + + + + + +50% +80% + + + diff --git a/inst/tinytest/test-type_text.R b/inst/tinytest/test-type_text.R index e49da13a..5d73af6c 100644 --- a/inst/tinytest/test-type_text.R +++ b/inst/tinytest/test-type_text.R @@ -29,3 +29,12 @@ f = function() { tinyplot(x, y, labels = z, type = "text") } expect_snapshot_plot(f, label = "text_single_character") + + +# labeller arg formats text labels, e.g. to match a formatted axis (#617) +f = function() { + d = data.frame(x = c("A", "B"), y = c(0.5, 0.8)) + tinyplot(y ~ x, data = d, type = "bar", ylim = c(0, 1), yaxl = "%") + tinyplot_add(type = type_text(labeller = "%", adj = c(0.5, -0.5))) +} +expect_snapshot_plot(f, label = "text_labeller_percent") diff --git a/man/type_text.Rd b/man/type_text.Rd index 03879c98..ed0e6703 100644 --- a/man/type_text.Rd +++ b/man/type_text.Rd @@ -6,6 +6,7 @@ \usage{ type_text( labels = NULL, + labeller = NULL, adj = NULL, pos = NULL, offset = 0.5, @@ -22,6 +23,12 @@ type_text( number of \code{x},\code{y} coordinates. If left as \code{NULL}, then the labels will automatically inherit the corresponding \code{y} values. See Examples.} +\item{labeller}{A formatting function (or convenience string) passed to +\code{\link{tinylabel}} for formatting the \code{labels}. Useful for ensuring that the +text labels match the formatting of an axis, e.g. \code{labeller = "\%"} to +display the labels as percentages. Default is \code{NULL}, i.e. no formatting. +See Examples.} + \item{adj}{one or two values in \eqn{[0, 1]} which specify the x (and optionally y) adjustment (\sQuote{justification}) of the labels, with 0 for left/bottom, 1 for right/top, and 0.5 for @@ -99,4 +106,9 @@ tinyplot(mpg ~ hp | factor(cyl), ) ) +# use `labeller` to format the labels, e.g. to match a formatted axis +d = data.frame(x = c("A", "B"), y = c(0.5, 0.8)) +tinyplot(y ~ x, data = d, type = "bar", ylim = c(0, 1), yaxl = "\%") +tinyplot_add(type = type_text(labeller = "\%", adj = c(0.5, -0.5))) + }