diff --git a/DESCRIPTION b/DESCRIPTION index 55905b784..97c981ac3 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: see Title: Model Visualisation Toolbox for 'easystats' and 'ggplot2' -Version: 0.13.0.3 +Version: 0.13.0.4 Authors@R: c(person(given = "Daniel", family = "Lüdecke", diff --git a/NAMESPACE b/NAMESPACE index baf540162..c96270233 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -83,13 +83,17 @@ export(flat_colors) export(geom_binomdensity) export(geom_count2) export(geom_count_borderless) +export(geom_count_halo) export(geom_from_list) export(geom_jitter2) export(geom_jitter_borderless) +export(geom_jitter_halo) export(geom_point2) export(geom_point_borderless) +export(geom_point_halo) export(geom_pointrange2) export(geom_pointrange_borderless) +export(geom_pointrange_halo) export(geom_pooljitter) export(geom_poolpoint) export(geom_violindot) diff --git a/NEWS.md b/NEWS.md index c69d58ce1..8011ffa5b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,14 @@ * Updated plot-method for `performance::check_model()` for Bayesian ordinal models. +* New `geom_point_halo()`, `geom_pointrange_halo()`, `geom_jitter_halo()` and + `geom_count_halo()` geoms, which add a slight contour around the points + +## Bug fixes + +* Fixed the `*_borderless` aliases for `geom_point2()` or `geom_jitter2()`, which + were broken and did not render as intended. + # see 0.13.0 ## Breaking Changes diff --git a/R/geom_point2.R b/R/geom_point2.R index 24389c93c..0e6c5e21e 100644 --- a/R/geom_point2.R +++ b/R/geom_point2.R @@ -1,19 +1,25 @@ -#' Better looking points +#' @title Better looking points +#' @name geom_point2 #' -#' Somewhat nicer points (especially in case of transparency) without outline -#' strokes (borders, contours) by default. +#' @description +#' The `*_borderless` geoms (and their shortcuts ending in `2`, such as `geom_point2` +#' or `geom_point_borderless`) render points without an outline stroke by default. +#' This prevents harsh edges and yields a smoother, cleaner look, especially when +#' using transparency. +#' +#' In contrast, the `*_halo` variants feature a border that automatically matches +#' the plot's background color. This creates a subtle visual separation (a "halo" +#' effect) that keeps overlapping points distinct. #' #' @param size Size of points. #' @param stroke Stroke thickness. #' @param shape Shape of points. -#' @param ... Other arguments to be passed to -#' [ggplot2::geom_point()], -#' [ggplot2::geom_jitter()], -#' [ggplot2::geom_pointrange()], or -#' [ggplot2::geom_count()]. +#' @param ... Other arguments to be passed to [ggplot2::geom_point()], +#' [ggplot2::geom_jitter()], [ggplot2::geom_pointrange()], or +#' [ggplot2::geom_count()]. #' -#' @note The color aesthetics for `geom_point_borderless()` is `"fill"`, not -#' `"color"`. See 'Examples'. +#' @note The color aesthetics for the `*_halo()` functions is `"fill"`, not +#' `"color"`. See 'Examples'. #' #' @examplesIf requireNamespace("patchwork", quietly = TRUE) #' library(ggplot2) @@ -29,13 +35,18 @@ #' #' plots(normal, new, n_columns = 2) #' -#' ggplot(iris, aes(x = Petal.Width, y = Sepal.Length, fill = Species)) + +#' ggplot(iris, aes(x = Petal.Width, y = Sepal.Length, color = Species)) + #' geom_point_borderless(size = 4) + #' theme_modern() #' #' theme_set(theme_abyss()) -#' ggplot(iris, aes(x = Petal.Width, y = Sepal.Length, fill = Species)) + +#' ggplot(iris, aes(x = Petal.Width, y = Sepal.Length, color = Species)) + #' geom_point_borderless(size = 4) +#' +#' # add "halo" effect - note that the aesthetics is "fill", not "color" +#' theme_set(theme_abyss()) +#' ggplot(iris, aes(x = Petal.Width, y = Sepal.Length, fill = Species)) + +#' geom_point_halo(size = 12) #' @export geom_point2 <- function(..., stroke = 0, shape = 16) { geom_point(stroke = stroke, shape = shape, ...) @@ -66,36 +77,75 @@ geom_count_borderless <- geom_count2 #' @rdname geom_point2 #' @export -geom_point_borderless <- function(...) { - geom_point(pch = 21, color = .get_theme_bg_color(), ...) +geom_point_borderless <- geom_point2 + + +#' @rdname geom_point2 +#' @export +geom_jitter_borderless <- geom_jitter2 + + +#' @rdname geom_point2 +#' @export +geom_pointrange_borderless <- geom_pointrange2 + + +#' @rdname geom_point2 +#' @export +geom_point_halo <- function(...) { + fun <- ggplot2::geom_point + .geom_halo(fun, ...) } #' @rdname geom_point2 #' @export -geom_jitter_borderless <- function(...) { - geom_jitter(pch = 21, color = .get_theme_bg_color(), ...) +geom_jitter_halo <- function(...) { + fun <- ggplot2::geom_jitter + .geom_halo(fun, ...) } #' @rdname geom_point2 #' @export -geom_pointrange_borderless <- function(...) { - geom_pointrange(pch = 21, color = .get_theme_bg_color(), ...) +geom_count_halo <- function(...) { + fun <- ggplot2::geom_count + .geom_halo(fun, ...) } -.get_theme_bg_color <- function() { - current_theme <- ggplot2::theme_get() +#' @rdname geom_point2 +#' @export +geom_pointrange_halo <- function(...) { + fun <- ggplot2::geom_pointrange + .geom_halo(fun, ...) +} + - if (is.null(current_theme$panel.grid.major)) { - current_theme$panel.grid.major <- current_theme$panel.grid +.geom_halo <- function(fun, ...) { + dots <- list(...) + if (!is.null(dots$color)) { + dots$fill <- dots$color } + if (!is.null(dots$colour)) { + dots$fill <- dots$colour + } + + dots$colour <- dots$shape <- dots$pch <- NULL + dots$color <- .get_theme_bg_color() + + fun_args <- c(list(pch = 21), dots) + do.call(fun, fun_args) +} + + +.get_theme_bg_color <- function() { + current_theme <- ggplot2::theme_get() bg_color <- ifelse( - is.null(current_theme$panel.grid.major$colour), + is.null(current_theme$panel.background$fill), "white", - current_theme$panel.grid.major$colour + current_theme$panel.background$fill ) bg_color diff --git a/man/geom_point2.Rd b/man/geom_point2.Rd index 17bc5ba68..d42a5ef06 100644 --- a/man/geom_point2.Rd +++ b/man/geom_point2.Rd @@ -9,6 +9,10 @@ \alias{geom_point_borderless} \alias{geom_jitter_borderless} \alias{geom_pointrange_borderless} +\alias{geom_point_halo} +\alias{geom_jitter_halo} +\alias{geom_count_halo} +\alias{geom_pointrange_halo} \title{Better looking points} \usage{ geom_point2(..., stroke = 0, shape = 16) @@ -21,17 +25,23 @@ geom_count2(..., stroke = 0) geom_count_borderless(..., stroke = 0) -geom_point_borderless(...) +geom_point_borderless(..., stroke = 0, shape = 16) -geom_jitter_borderless(...) +geom_jitter_borderless(..., size = 2, stroke = 0, shape = 16) -geom_pointrange_borderless(...) +geom_pointrange_borderless(..., stroke = 0) + +geom_point_halo(...) + +geom_jitter_halo(...) + +geom_count_halo(...) + +geom_pointrange_halo(...) } \arguments{ -\item{...}{Other arguments to be passed to -\code{\link[ggplot2:geom_point]{ggplot2::geom_point()}}, -\code{\link[ggplot2:geom_jitter]{ggplot2::geom_jitter()}}, -\code{\link[ggplot2:geom_pointrange]{ggplot2::geom_pointrange()}}, or +\item{...}{Other arguments to be passed to \code{\link[ggplot2:geom_point]{ggplot2::geom_point()}}, +\code{\link[ggplot2:geom_jitter]{ggplot2::geom_jitter()}}, \code{\link[ggplot2:geom_pointrange]{ggplot2::geom_pointrange()}}, or \code{\link[ggplot2:geom_count]{ggplot2::geom_count()}}.} \item{stroke}{Stroke thickness.} @@ -41,11 +51,17 @@ geom_pointrange_borderless(...) \item{size}{Size of points.} } \description{ -Somewhat nicer points (especially in case of transparency) without outline -strokes (borders, contours) by default. +The \verb{*_borderless} geoms (and their shortcuts ending in \code{2}, such as \code{geom_point2} +or \code{geom_point_borderless}) render points without an outline stroke by default. +This prevents harsh edges and yields a smoother, cleaner look, especially when +using transparency. + +In contrast, the \verb{*_halo} variants feature a border that automatically matches +the plot's background color. This creates a subtle visual separation (a "halo" +effect) that keeps overlapping points distinct. } \note{ -The color aesthetics for \code{geom_point_borderless()} is \code{"fill"}, not +The color aesthetics for the \verb{*_halo()} functions is \code{"fill"}, not \code{"color"}. See 'Examples'. } \examples{ @@ -63,12 +79,17 @@ new <- ggplot(iris, aes(x = Petal.Width, y = Sepal.Length)) + plots(normal, new, n_columns = 2) -ggplot(iris, aes(x = Petal.Width, y = Sepal.Length, fill = Species)) + +ggplot(iris, aes(x = Petal.Width, y = Sepal.Length, color = Species)) + geom_point_borderless(size = 4) + theme_modern() theme_set(theme_abyss()) -ggplot(iris, aes(x = Petal.Width, y = Sepal.Length, fill = Species)) + +ggplot(iris, aes(x = Petal.Width, y = Sepal.Length, color = Species)) + geom_point_borderless(size = 4) + +# add "halo" effect - note that the aesthetics is "fill", not "color" +theme_set(theme_abyss()) +ggplot(iris, aes(x = Petal.Width, y = Sepal.Length, fill = Species)) + + geom_point_halo(size = 12) \dontshow{\}) # examplesIf} } diff --git a/tests/testthat/_snaps/vdiffr_geoms_borderless/geom-point-borderless-1.svg b/tests/testthat/_snaps/vdiffr_geoms_borderless/geom-point-borderless-1.svg new file mode 100644 index 000000000..fd89bb248 --- /dev/null +++ b/tests/testthat/_snaps/vdiffr_geoms_borderless/geom-point-borderless-1.svg @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +5 +6 +7 +8 + +0.0 +0.5 +1.0 +1.5 +2.0 +2.5 +Petal.Width +Sepal.Length + +Species + + + +setosa +versicolor +virginica +geom_point_borderless_1 + + diff --git a/tests/testthat/_snaps/vdiffr_geoms_borderless/geom-point-borderless-2.svg b/tests/testthat/_snaps/vdiffr_geoms_borderless/geom-point-borderless-2.svg new file mode 100644 index 000000000..933d531ba --- /dev/null +++ b/tests/testthat/_snaps/vdiffr_geoms_borderless/geom-point-borderless-2.svg @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +5 +6 +7 +8 + +0.0 +0.5 +1.0 +1.5 +2.0 +2.5 +Petal.Width +Sepal.Length + +Species + + + +setosa +versicolor +virginica +geom_point_borderless_2 + + diff --git a/tests/testthat/_snaps/vdiffr_geoms_borderless/geom-point-halo-1.svg b/tests/testthat/_snaps/vdiffr_geoms_borderless/geom-point-halo-1.svg new file mode 100644 index 000000000..46a4400b6 --- /dev/null +++ b/tests/testthat/_snaps/vdiffr_geoms_borderless/geom-point-halo-1.svg @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +5 +6 +7 +8 + +0.0 +0.5 +1.0 +1.5 +2.0 +2.5 +Petal.Width +Sepal.Length + +Species + + + +setosa +versicolor +virginica +geom_point_halo_1 + + diff --git a/tests/testthat/test-vdiffr_geoms_borderless.R b/tests/testthat/test-vdiffr_geoms_borderless.R new file mode 100644 index 000000000..c7eb5fa4b --- /dev/null +++ b/tests/testthat/test-vdiffr_geoms_borderless.R @@ -0,0 +1,47 @@ +test_that("borderless geoms work correctly", { + skip_on_cran() + skip_if_not_installed("ggplot2") + skip_if_not_installed("vdiffr") + data(iris) + + p <- ggplot2::ggplot( + iris, + ggplot2::aes(x = Petal.Width, y = Sepal.Length, color = Species) + ) + + geom_point_borderless(size = 4) + + theme_modern() + + set.seed(123) + vdiffr::expect_doppelganger( + title = "geom_point_borderless_1", + fig = p + ) + + ggplot2::theme_set(theme_abyss()) + p <- ggplot2::ggplot( + iris, + ggplot2::aes(x = Petal.Width, y = Sepal.Length, color = Species) + ) + + theme_abyss() + + geom_point_borderless(size = 4) + + set.seed(123) + vdiffr::expect_doppelganger( + title = "geom_point_borderless_2", + fig = p + ) + + ggplot2::theme_set(theme_abyss()) + p <- ggplot2::ggplot( + iris, + ggplot2::aes(x = Petal.Width, y = Sepal.Length, fill = Species) + ) + + theme_abyss() + + geom_point_halo(size = 12) + + set.seed(123) + vdiffr::expect_doppelganger( + title = "geom_point_halo_1", + fig = p + ) +})