diff --git a/NEWS.md b/NEWS.md index a4bce3f6be..5df6059f0f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # ggplot2 (development version) +* Built-in `theme_*()` functions now have `ink` and `paper` arguments to control + foreground and background colours respectively (@teunbrand) * The `summary()` method for ggplots is now more terse about facets (@teunbrand, #5989). * `guide_bins()`, `guide_colourbar()` and `guide_coloursteps()` gain an `angle` diff --git a/R/theme-defaults.R b/R/theme-defaults.R index 77b36e243e..8be7999d4d 100644 --- a/R/theme-defaults.R +++ b/R/theme-defaults.R @@ -11,6 +11,7 @@ #' legend titles, the plot title and tag text. #' @param base_line_size base size for line elements #' @param base_rect_size base size for rect elements +#' @param ink,paper colour for foreground and background elements respectively. #' #' @details #' \describe{ @@ -106,7 +107,8 @@ NULL theme_grey <- function(base_size = 11, base_family = "", header_family = NULL, base_line_size = base_size / 22, - base_rect_size = base_size / 22) { + base_rect_size = base_size / 22, + ink = "black", paper = "white") { # The half-line (base-fontsize / 2) sets up the basic vertical # rhythm of the theme. Most margins will be set to this value. @@ -124,16 +126,16 @@ theme_grey <- function(base_size = 11, base_family = "", # Elements in this first block aren't used directly, but are inherited # by others line = element_line( - colour = "black", linewidth = base_line_size, + colour = ink, linewidth = base_line_size, linetype = 1, lineend = "butt" ), rect = element_rect( - fill = "white", colour = "black", + fill = paper, colour = ink, linewidth = base_rect_size, linetype = 1 ), text = element_text( family = base_family, face = "plain", - colour = "black", size = base_size, + colour = ink, size = base_size, lineheight = 0.9, hjust = 0.5, vjust = 0.5, angle = 0, margin = margin(), debug = FALSE ), @@ -144,7 +146,7 @@ theme_grey <- function(base_size = 11, base_family = "", margins = margin(half_line, half_line, half_line, half_line), geom = element_geom( - ink = "black", paper = "white", accent = "#3366FF", + ink = ink, paper = paper, accent = "#3366FF", linewidth = base_line_size, borderwidth = base_line_size, linetype = 1L, bordertype = 1L, family = base_family, fontsize = base_size, @@ -154,14 +156,14 @@ theme_grey <- function(base_size = 11, base_family = "", axis.line = element_blank(), axis.line.x = NULL, axis.line.y = NULL, - axis.text = element_text(size = rel(0.8), colour = "grey30"), + axis.text = element_text(size = rel(0.8), colour = col_mix(ink, paper, 0.305)), axis.text.x = element_text(margin = margin(t = 0.8 * half_line / 2), vjust = 1), axis.text.x.top = element_text(margin = margin(b = 0.8 * half_line / 2), vjust = 0), axis.text.y = element_text(margin = margin(r = 0.8 * half_line / 2), hjust = 1), axis.text.y.right = element_text(margin = margin(l = 0.8 * half_line / 2), hjust = 0), axis.text.r = element_text(margin = margin(l = 0.8 * half_line / 2, r = 0.8 * half_line / 2), hjust = 0.5), - axis.ticks = element_line(colour = "grey20"), + axis.ticks = element_line(colour = col_mix(ink, paper, 0.2)), axis.ticks.length = rel(0.5), axis.ticks.length.x = NULL, axis.ticks.length.x.top = NULL, @@ -210,19 +212,19 @@ theme_grey <- function(base_size = 11, base_family = "", legend.box.background = element_blank(), legend.box.spacing = rel(2), - panel.background = element_rect(fill = "grey92", colour = NA), + panel.background = element_rect(fill = col_mix(ink, paper, 0.925), colour = NA), panel.border = element_blank(), - panel.grid = element_line(colour = "white"), + panel.grid = element_line(colour = paper), panel.grid.minor = element_line(linewidth = rel(0.5)), panel.spacing = NULL, panel.spacing.x = NULL, panel.spacing.y = NULL, panel.ontop = FALSE, - strip.background = element_rect(fill = "grey85", colour = NA), + strip.background = element_rect(fill = col_mix(ink, paper, 0.854), colour = NA), strip.clip = "on", strip.text = element_text( - colour = "grey10", + colour = col_mix(ink, paper, 0.105), size = rel(0.8), margin = margin(0.8 * half_line, 0.8 * half_line, 0.8 * half_line, 0.8 * half_line) ), @@ -235,7 +237,7 @@ theme_grey <- function(base_size = 11, base_family = "", strip.switch.pad.grid = unit(half_line / 2, "pt"), strip.switch.pad.wrap = unit(half_line / 2, "pt"), - plot.background = element_rect(colour = "white"), + plot.background = element_rect(colour = paper), plot.title = element_text( # font size "large" size = rel(1.2), hjust = 0, vjust = 1, @@ -274,24 +276,29 @@ theme_gray <- theme_grey theme_bw <- function(base_size = 11, base_family = "", header_family = NULL, base_line_size = base_size / 22, - base_rect_size = base_size / 22) { + base_rect_size = base_size / 22, + ink = "black", paper = "white") { # Starts with theme_grey and then modify some parts theme_grey( base_size = base_size, base_family = base_family, header_family = header_family, base_line_size = base_line_size, - base_rect_size = base_rect_size + base_rect_size = base_rect_size, + ink = ink, paper = paper ) %+replace% theme( # white background and dark border - panel.background = element_rect(fill = "white", colour = NA), - panel.border = element_rect(colour = "grey20"), + panel.background = element_rect(fill = paper, colour = NA), + panel.border = element_rect(colour = col_mix(ink, paper, 0.2)), # make gridlines dark, same contrast with white as in theme_grey - panel.grid = element_line(colour = "grey92"), + panel.grid = element_line(colour = col_mix(ink, paper, 0.925)), panel.grid.minor = element_line(linewidth = rel(0.5)), # contour strips to match panel contour - strip.background = element_rect(fill = "grey85", colour = "grey20"), + strip.background = element_rect( + fill = col_mix(ink, paper, 0.851), + colour = col_mix(ink, paper, 0.2) + ), complete = TRUE ) @@ -302,7 +309,8 @@ theme_bw <- function(base_size = 11, base_family = "", theme_linedraw <- function(base_size = 11, base_family = "", header_family = NULL, base_line_size = base_size / 22, - base_rect_size = base_size / 22) { + base_rect_size = base_size / 22, + ink = "black", paper = "white") { half_line <- base_size / 2 # Starts with theme_bw and then modify some parts @@ -312,25 +320,26 @@ theme_linedraw <- function(base_size = 11, base_family = "", base_family = base_family, header_family = header_family, base_line_size = base_line_size, - base_rect_size = base_rect_size + base_rect_size = base_rect_size, + ink = ink, paper = paper ) %+replace% theme( # black text and ticks on the axes - axis.text = element_text(colour = "black", size = rel(0.8)), - axis.ticks = element_line(colour = "black", linewidth = rel(0.5)), + axis.text = element_text(colour = ink, size = rel(0.8)), + axis.ticks = element_line(colour = ink, linewidth = rel(0.5)), # NB: match the *visual* thickness of axis ticks to the panel border # 0.5 clipped looks like 0.25 # pure black panel border and grid lines, but thinner - panel.border = element_rect(colour = "black", linewidth = rel(1)), - panel.grid = element_line(colour = "black"), + panel.border = element_rect(colour = ink, linewidth = rel(1)), + panel.grid = element_line(colour = ink), panel.grid.major = element_line(linewidth = rel(0.1)), panel.grid.minor = element_line(linewidth = rel(0.05)), # strips with black background and white text - strip.background = element_rect(fill = "black"), + strip.background = element_rect(fill = ink), strip.text = element_text( - colour = "white", + colour = paper, size = rel(0.8), margin = margin(0.8 * half_line, 0.8 * half_line, 0.8 * half_line, 0.8 * half_line) ), @@ -344,7 +353,8 @@ theme_linedraw <- function(base_size = 11, base_family = "", theme_light <- function(base_size = 11, base_family = "", header_family = NULL, base_line_size = base_size / 22, - base_rect_size = base_size / 22) { + base_rect_size = base_size / 22, + ink = "black", paper = "white") { half_line <- base_size / 2 # Starts with theme_grey and then modify some parts @@ -353,25 +363,26 @@ theme_light <- function(base_size = 11, base_family = "", base_family = base_family, header_family = header_family, base_line_size = base_line_size, - base_rect_size = base_rect_size + base_rect_size = base_rect_size, + ink = ink, paper = paper ) %+replace% theme( # white panel with light grey border - panel.background = element_rect(fill = "white", colour = NA), - panel.border = element_rect(colour = "grey70", linewidth = rel(1)), + panel.background = element_rect(fill = paper, colour = NA), + panel.border = element_rect(colour = col_mix(ink, paper, 0.705), linewidth = rel(1)), # light grey, thinner gridlines # => make them slightly darker to keep acceptable contrast - panel.grid = element_line(colour = "grey87"), + panel.grid = element_line(colour = col_mix(ink, paper, 0.871)), panel.grid.major = element_line(linewidth = rel(0.5)), panel.grid.minor = element_line(linewidth = rel(0.25)), # match axes ticks thickness to gridlines and colour to panel border - axis.ticks = element_line(colour = "grey70", linewidth = rel(0.5)), + axis.ticks = element_line(colour = col_mix(ink, paper, 0.705), linewidth = rel(0.5)), # dark strips with light text (inverse contrast compared to theme_grey) - strip.background = element_rect(fill = "grey70", colour = NA), + strip.background = element_rect(fill = col_mix(ink, paper, 0.705), colour = NA), strip.text = element_text( - colour = "white", + colour = paper, size = rel(0.8), margin = margin(0.8 * half_line, 0.8 * half_line, 0.8 * half_line, 0.8 * half_line) ), @@ -386,7 +397,8 @@ theme_light <- function(base_size = 11, base_family = "", theme_dark <- function(base_size = 11, base_family = "", header_family = NULL, base_line_size = base_size / 22, - base_rect_size = base_size / 22) { + base_rect_size = base_size / 22, + ink = "black", paper = "white") { half_line <- base_size / 2 # Starts with theme_grey and then modify some parts @@ -395,24 +407,25 @@ theme_dark <- function(base_size = 11, base_family = "", base_family = base_family, header_family = header_family, base_line_size = base_line_size, - base_rect_size = base_rect_size + base_rect_size = base_rect_size, + ink = ink, paper = paper ) %+replace% theme( # dark panel - panel.background = element_rect(fill = "grey50", colour = NA), + panel.background = element_rect(fill = col_mix(ink, paper, 0.5), colour = NA), # inverse grid lines contrast compared to theme_grey # make them thinner and try to keep the same visual contrast as in theme_light - panel.grid = element_line(colour = "grey42"), + panel.grid = element_line(colour = col_mix(ink, paper, 0.42)), panel.grid.major = element_line(linewidth = rel(0.5)), panel.grid.minor = element_line(linewidth = rel(0.25)), # match axes ticks thickness to gridlines - axis.ticks = element_line(colour = "grey20", linewidth = rel(0.5)), + axis.ticks = element_line(colour = col_mix(ink, paper, 0.2), linewidth = rel(0.5)), # dark strips with light text (inverse contrast compared to theme_grey) - strip.background = element_rect(fill = "grey15", colour = NA), + strip.background = element_rect(fill = col_mix(ink, paper, 0.15), colour = NA), strip.text = element_text( - colour = "grey90", + colour = col_mix(ink, paper, 0.9), size = rel(0.8), margin = margin(0.8 * half_line, 0.8 * half_line, 0.8 * half_line, 0.8 * half_line) ), @@ -426,17 +439,19 @@ theme_dark <- function(base_size = 11, base_family = "", theme_minimal <- function(base_size = 11, base_family = "", header_family = NULL, base_line_size = base_size / 22, - base_rect_size = base_size / 22) { + base_rect_size = base_size / 22, + ink = "black", paper = "white") { # Starts with theme_bw and remove most parts theme_bw( base_size = base_size, base_family = base_family, header_family = header_family, base_line_size = base_line_size, - base_rect_size = base_rect_size + base_rect_size = base_rect_size, + ink = ink, paper = paper ) %+replace% theme( - axis.ticks = element_blank(), + axis.ticks = element_blank(), legend.background = element_blank(), legend.key = element_blank(), panel.background = element_blank(), @@ -453,13 +468,15 @@ theme_minimal <- function(base_size = 11, base_family = "", theme_classic <- function(base_size = 11, base_family = "", header_family = NULL, base_line_size = base_size / 22, - base_rect_size = base_size / 22) { + base_rect_size = base_size / 22, + ink = "black", paper = "white") { theme_bw( base_size = base_size, base_family = base_family, header_family = header_family, base_line_size = base_line_size, - base_rect_size = base_rect_size + base_rect_size = base_rect_size, + ink = ink, paper = paper ) %+replace% theme( # no background and no grid @@ -485,7 +502,8 @@ theme_classic <- function(base_size = 11, base_family = "", theme_void <- function(base_size = 11, base_family = "", header_family = NULL, base_line_size = base_size / 22, - base_rect_size = base_size / 22) { + base_rect_size = base_size / 22, + ink = "black", paper = "white") { half_line <- base_size / 2 # Only keep indispensable text: legend and plot titles @@ -494,7 +512,7 @@ theme_void <- function(base_size = 11, base_family = "", rect = element_blank(), text = element_text( family = base_family, face = "plain", - colour = "black", size = base_size, + colour = ink, size = base_size, lineheight = 0.9, hjust = 0.5, vjust = 0.5, angle = 0, margin = margin(), debug = FALSE ), @@ -563,21 +581,22 @@ theme_void <- function(base_size = 11, base_family = "", theme_test <- function(base_size = 11, base_family = "", header_family = NULL, base_line_size = base_size / 22, - base_rect_size = base_size / 22) { + base_rect_size = base_size / 22, + ink = "black", paper = "white") { half_line <- base_size / 2 t <- theme( line = element_line( - colour = "black", linewidth = base_line_size, + colour = ink, linewidth = base_line_size, linetype = 1, lineend = "butt" ), rect = element_rect( - fill = "white", colour = "black", + fill = paper, colour = ink, linewidth = base_rect_size, linetype = 1 ), text = element_text( family = base_family, face = "plain", - colour = "black", size = base_size, + colour = ink, size = base_size, lineheight = 0.9, hjust = 0.5, vjust = 0.5, angle = 0, margin = margin(), debug = FALSE ), @@ -585,7 +604,7 @@ theme_test <- function(base_size = 11, base_family = "", spacing = unit(half_line, "pt"), margins = margin(half_line, half_line, half_line, half_line), geom = element_geom( - ink = "black", paper = "white", accent = "#3366FF", + ink = ink, paper = paper, accent = "#3366FF", linewidth = base_line_size, borderwidth = base_line_size, family = base_family, fontsize = base_size, linetype = 1L, @@ -595,12 +614,12 @@ theme_test <- function(base_size = 11, base_family = "", axis.line = element_blank(), axis.line.x = NULL, axis.line.y = NULL, - axis.text = element_text(size = rel(0.8), colour = "grey30"), + axis.text = element_text(size = rel(0.8), colour = col_mix(ink, paper, 0.305)), axis.text.x = element_text(margin = margin(t = 0.8 * half_line / 2), vjust = 1), axis.text.x.top = element_text(margin = margin(b = 0.8 * half_line / 2), vjust = 0), axis.text.y = element_text(margin = margin(r = 0.8 * half_line / 2), hjust = 1), axis.text.y.right = element_text(margin = margin(l = 0.8 * half_line / 2), hjust = 0), - axis.ticks = element_line(colour = "grey20"), + axis.ticks = element_line(colour = col_mix(ink, paper, 0.2)), axis.ticks.length = rel(0.5), axis.ticks.length.x = NULL, axis.ticks.length.x.top = NULL, @@ -651,8 +670,8 @@ theme_test <- function(base_size = 11, base_family = "", legend.box.background = element_blank(), legend.box.spacing = rel(2), - panel.background = element_rect(fill = "white", colour = NA), - panel.border = element_rect(colour = "grey20"), + panel.background = element_rect(fill = paper, colour = NA), + panel.border = element_rect(colour = col_mix(ink, paper, 0.2)), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.spacing = NULL, @@ -660,10 +679,13 @@ theme_test <- function(base_size = 11, base_family = "", panel.spacing.y = NULL, panel.ontop = FALSE, - strip.background = element_rect(fill = "grey85", colour = "grey20"), + strip.background = element_rect( + fill = col_mix(ink, paper, 0.851), + colour = col_mix(ink, paper, 0.2) + ), strip.clip = "on", strip.text = element_text( - colour = "grey10", + colour = col_mix(ink, paper, 0.105), size = rel(0.8), margin = margin(0.8 * half_line, 0.8 * half_line, 0.8 * half_line, 0.8 * half_line) ), @@ -676,7 +698,7 @@ theme_test <- function(base_size = 11, base_family = "", strip.switch.pad.grid = rel(0.5), strip.switch.pad.wrap = rel(0.5), - plot.background = element_rect(colour = "white"), + plot.background = element_rect(colour = paper), plot.title = element_text( size = rel(1.2), hjust = 0, vjust = 1, diff --git a/man/ggtheme.Rd b/man/ggtheme.Rd index 642319bcc9..e86accb182 100644 --- a/man/ggtheme.Rd +++ b/man/ggtheme.Rd @@ -18,7 +18,9 @@ theme_grey( base_family = "", header_family = NULL, base_line_size = base_size/22, - base_rect_size = base_size/22 + base_rect_size = base_size/22, + ink = "black", + paper = "white" ) theme_gray( @@ -26,7 +28,9 @@ theme_gray( base_family = "", header_family = NULL, base_line_size = base_size/22, - base_rect_size = base_size/22 + base_rect_size = base_size/22, + ink = "black", + paper = "white" ) theme_bw( @@ -34,7 +38,9 @@ theme_bw( base_family = "", header_family = NULL, base_line_size = base_size/22, - base_rect_size = base_size/22 + base_rect_size = base_size/22, + ink = "black", + paper = "white" ) theme_linedraw( @@ -42,7 +48,9 @@ theme_linedraw( base_family = "", header_family = NULL, base_line_size = base_size/22, - base_rect_size = base_size/22 + base_rect_size = base_size/22, + ink = "black", + paper = "white" ) theme_light( @@ -50,7 +58,9 @@ theme_light( base_family = "", header_family = NULL, base_line_size = base_size/22, - base_rect_size = base_size/22 + base_rect_size = base_size/22, + ink = "black", + paper = "white" ) theme_dark( @@ -58,7 +68,9 @@ theme_dark( base_family = "", header_family = NULL, base_line_size = base_size/22, - base_rect_size = base_size/22 + base_rect_size = base_size/22, + ink = "black", + paper = "white" ) theme_minimal( @@ -66,7 +78,9 @@ theme_minimal( base_family = "", header_family = NULL, base_line_size = base_size/22, - base_rect_size = base_size/22 + base_rect_size = base_size/22, + ink = "black", + paper = "white" ) theme_classic( @@ -74,7 +88,9 @@ theme_classic( base_family = "", header_family = NULL, base_line_size = base_size/22, - base_rect_size = base_size/22 + base_rect_size = base_size/22, + ink = "black", + paper = "white" ) theme_void( @@ -82,7 +98,9 @@ theme_void( base_family = "", header_family = NULL, base_line_size = base_size/22, - base_rect_size = base_size/22 + base_rect_size = base_size/22, + ink = "black", + paper = "white" ) theme_test( @@ -90,7 +108,9 @@ theme_test( base_family = "", header_family = NULL, base_line_size = base_size/22, - base_rect_size = base_size/22 + base_rect_size = base_size/22, + ink = "black", + paper = "white" ) } \arguments{ @@ -105,6 +125,8 @@ legend titles, the plot title and tag text.} \item{base_line_size}{base size for line elements} \item{base_rect_size}{base size for rect elements} + +\item{ink, paper}{colour for foreground and background elements respectively.} } \description{ These are complete themes which control all non-data display. Use diff --git a/tests/testthat/_snaps/theme/theme-with-inverted-colours.svg b/tests/testthat/_snaps/theme/theme-with-inverted-colours.svg new file mode 100644 index 0000000000..812529cf9f --- /dev/null +++ b/tests/testthat/_snaps/theme/theme-with-inverted-colours.svg @@ -0,0 +1,332 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Strip title + + + + + + + + +2 +3 +4 +5 +6 +7 +20 +30 +40 + + + +displ +hwy + +drv + + + + + + +4 +f +r +Subtitle +Main title +Caption +A + + diff --git a/tests/testthat/test-theme.R b/tests/testthat/test-theme.R index 9c10202504..36ad577c65 100644 --- a/tests/testthat/test-theme.R +++ b/tests/testthat/test-theme.R @@ -840,6 +840,24 @@ test_that("Strips can render custom elements", { expect_doppelganger("custom strip elements can render", plot) }) +test_that("theme ink and paper settings work", { + + p <- ggplot(mpg, aes(displ, hwy, colour = drv)) + + geom_point() + + facet_wrap(~"Strip title") + + labs( + title = "Main title", + subtitle = "Subtitle", + tag = "A", + caption = "Caption" + ) + + expect_doppelganger( + "Theme with inverted colours", + p + theme_gray(ink = "white", paper = "black") + ) +}) + test_that("legend margins are correct when using relative key sizes", { df <- data_frame(x = 1:3, y = 1:3, a = letters[1:3])