diff --git a/NAMESPACE b/NAMESPACE index 13b7e9bc..0d4b5af3 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -115,7 +115,6 @@ export(extended_breaks) export(format_format) export(format_log) export(fullseq) -export(get_palette) export(gradient_n_pal) export(grey_pal) export(hms_trans) @@ -199,7 +198,6 @@ export(pal_seq_gradient) export(pal_shape) export(pal_viridis) export(palette_na_safe) -export(palette_names) export(palette_nlevels) export(palette_type) export(parse_format) @@ -218,12 +216,10 @@ export(rescale_max) export(rescale_mid) export(rescale_none) export(rescale_pal) -export(reset_palettes) export(reverse_trans) export(scientific) export(scientific_format) export(seq_gradient_pal) -export(set_palette) export(shape_pal) export(show_col) export(sqrt_trans) diff --git a/R/pal-.R b/R/pal-.R index 66d1f27f..d465595b 100644 --- a/R/pal-.R +++ b/R/pal-.R @@ -1,3 +1,89 @@ +#' @name palette-recommendations +#' @title Recommendations for colour palettes +#' @description +#' For the purposes of these recommendations, we define a palette as a function +#' that either takes an `n` argument for the number of desired output colours or +#' a `value` argument between 0-1 representing how far along a gradient output +#' colours should be. The palette then returns a number of colours equal to `n` +#' or `length(x)`. +#' +#' The convention in the scales package is to name functions that generate +#' palettes (palette factories) with the `pal_`-prefix. The benefit of +#' factories is that you can easily parameterise palettes, for example giving +#' options for how a palette should be constructed. +#' +#' In the example below `pal_aurora()` is a palette factory parameterised by +#' a `direction` argument. +#' +#' ```r +#' pal_aurora <- function(direction = 1) { +#' colours <- c("palegreen", "deepskyblue", "magenta") +#' if (sign(direction) == -1) { +#' colours <- rev(colours) +#' } +#' pal_manual(colours, type = "colour") +#' } +#' +#' class(pal_aurora()) +#' #> [1] "pal_discrete" "scales_pal" "function" +#' ``` +#' +#' It is recommended that a palette factory returns a function with either the +#' `pal_discrete` or `pal_continuous` class. If your factory constructs a +#' plain vector of colours, then `pal_manual(type = "colour")` or +#' `pal_gradient_n()` are useful to return a classed palette for this common +#' use case. +#' +#' When your inner palette function does not return a defined vector of colours, +#' it is recommended to use `new_discrete_palette` and `new_continuous_palette` +#' instead and supplement the additional `type` and `na_safe`/`nlevels` +#' properties. This should allow easy translation between discrete and +#' continuous palettes. +#' +#' ```r +#' pal_random <- function() { +#' fun <- function(n) { +#' sample(colours(distinct = TRUE), size = n) +#' } +#' new_discrete_palette(fun, type = "colour", nlevels = length(colours())) +#' } +#' ``` +#' +#' If you don't have parameterised palettes, but also if you have palette +#' factories, it is encouraged to export an (inner) palette function or +#' plain colour vector. This is in addition to exporting the palette factory. +#' Exporting this makes it easy for users to specify for example +#' `as_continuous_pal(mypackage::aurora)`. +#' +#' ``` +#' #' @export +#' aurora <- pal_aurora() +#' +#' # or: +#' +#' #' @export +#' aurora <- c("palegreen", "deepskyblue", "magenta") +#' ``` +#' +#' Lastly, for testing purposes we encourage that your palettes can be +#' interpreted both as discrete palette, but also a continuous palette. +#' To test for this, you can test the output of `as_discrete_pal()` and +#' `as_continuous_pal()`. +#' +#' ```r +#' test_that("pal_aurora can be discrete or continuous", { +#' +#' my_pal <- pal_aurora() +#' colours <- c("palegreen", "deepskyblue", "magenta") +#' +#' expect_equal(as_discrete_pal(my_pal)(3), colours) +#' expect_equal(as_continuous_pal(my_pal)(c(0, 0.5, 1)), alpha(colours, NA)) +#' +#' }) +#' ``` +#' @seealso [palette utilities][new_continuous_palette] +NULL + # Constructors ------------------------------------------------------------ #' Constructors for palettes @@ -28,6 +114,7 @@ #' For `palette_nlevels()` a single integer. For `palette_na_safe()` a boolean. #' For `palette_type()` a string. #' @export +#' @seealso [palette recommendations][palette-recommendations] #' #' @examples #' # Creating a new discrete palette diff --git a/R/palette-registry.R b/R/palette-registry.R index 6ef38ab7..0542716d 100644 --- a/R/palette-registry.R +++ b/R/palette-registry.R @@ -16,7 +16,7 @@ #' #' @return The `get_palette()` function returns a palette. The `set_palette()` #' function is called for side effects and returns nothing. -#' @export +#' @noRd #' #' @examples #' # Get one of the known palettes @@ -61,8 +61,6 @@ get_palette <- function(name, ...) { cli::cli_abort("Failed to interpret {name} as palette.") } -#' @export -#' @rdname get_palette set_palette <- function(name, palette, warn_conflict = TRUE) { name <- tolower(name) if (!is_function(palette) && !is_character(palette)) { @@ -78,14 +76,10 @@ set_palette <- function(name, palette, warn_conflict = TRUE) { invisible(NULL) } -#' @export -#' @rdname get_palette palette_names <- function() { names(.known_palettes) } -#' @export -#' @rdname get_palette reset_palettes <- function() { env_unbind(.known_palettes, palette_names()) init_palettes() diff --git a/_pkgdown.yml b/_pkgdown.yml index 517a9750..e53339f7 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -71,7 +71,7 @@ reference: - contains("col") - muted - alpha - - get_palette + - palette-recommendations - title: Non-colour palette functions desc: > diff --git a/man/get_palette.Rd b/man/get_palette.Rd deleted file mode 100644 index e48def8e..00000000 --- a/man/get_palette.Rd +++ /dev/null @@ -1,53 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/palette-registry.R -\name{get_palette} -\alias{get_palette} -\alias{set_palette} -\alias{palette_names} -\alias{reset_palettes} -\title{Known palettes} -\usage{ -get_palette(name, ...) - -set_palette(name, palette, warn_conflict = TRUE) - -palette_names() - -reset_palettes() -} -\arguments{ -\item{name}{A string giving the palette name.} - -\item{...}{Additional arguments to pass to palette when it is a function -but not a palette class function.} - -\item{palette}{A \link[=new_continuous_palette]{palette}, \code{function} or character -vector.} - -\item{warn_conflict}{A boolean which if \code{TRUE} (default), warns when -replacing a known palette.} -} -\value{ -The \code{get_palette()} function returns a palette. The \code{set_palette()} -function is called for side effects and returns nothing. -} -\description{ -The scales packages keeps track of a set of palettes it considers 'known'. -The benefit of a known palette is that it can be called by name in functions -as \code{as_continuous_pal()} or \code{as_discrete_pal()}. -} -\examples{ -# Get one of the known palettes -get_palette("hue") - -# Set a new custom palette -cols <- c("palegreen", "deepskyblue", "magenta") -set_palette("aurora", palette = cols) - -# Palette is now known -"aurora" \%in\% palette_names() -as_continuous_pal("aurora") - -# Resetting palettes -reset_palettes() -} diff --git a/man/new_continuous_palette.Rd b/man/new_continuous_palette.Rd index 49860805..cf0b1585 100644 --- a/man/new_continuous_palette.Rd +++ b/man/new_continuous_palette.Rd @@ -106,3 +106,6 @@ show_col(pal(c(0, 0.1, 0.2, 0.4, 1))) pal <- as_discrete_pal(pal_div_gradient()) show_col(pal(9)) } +\seealso{ +\link[=palette-recommendations]{palette recommendations} +} diff --git a/man/palette-recommendations.Rd b/man/palette-recommendations.Rd new file mode 100644 index 00000000..0f0be9de --- /dev/null +++ b/man/palette-recommendations.Rd @@ -0,0 +1,86 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/pal-.R +\name{palette-recommendations} +\alias{palette-recommendations} +\title{Recommendations for colour palettes} +\description{ +For the purposes of these recommendations, we define a palette as a function +that either takes an \code{n} argument for the number of desired output colours or +a \code{value} argument between 0-1 representing how far along a gradient output +colours should be. The palette then returns a number of colours equal to \code{n} +or \code{length(x)}. + +The convention in the scales package is to name functions that generate +palettes (palette factories) with the \code{pal_}-prefix. The benefit of +factories is that you can easily parameterise palettes, for example giving +options for how a palette should be constructed. + +In the example below \code{pal_aurora()} is a palette factory parameterised by +a \code{direction} argument. + +\if{html}{\out{