wilkelab / ggtext

Improved text rendering support for ggplot2
https://wilkelab.org/ggtext/
GNU General Public License v2.0
651 stars 37 forks source link

background color in element_markdown() #27

Closed fmmattioni closed 3 years ago

fmmattioni commented 4 years ago

I would like to apply a background color to axis.text as it is applied in axis.title in the following example:

Expand example ``` r library(ggplot2) library(ggtext) ggplot(mtcars, aes(disp, mpg)) + geom_point() + labs( title = "Fuel economy vs. engine displacement
Lorem ipsum *dolor sit amet,* consectetur adipiscing elit, **sed do eiusmod tempor incididunt** ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", x = "displacement (in3)", y = "Miles per gallon (mpg)
A measure of the car's fuel efficiency." ) + theme( plot.title.position = "plot", plot.title = element_textbox_simple( size = 13, lineheight = 1, padding = margin(5.5, 5.5, 5.5, 5.5), margin = margin(0, 0, 5.5, 0), fill = "cornsilk" ), axis.title.x = element_textbox_simple( width = NULL, padding = margin(4, 4, 4, 4), margin = margin(4, 0, 0, 0), linetype = 1, r = grid::unit(8, "pt"), fill = "azure1" ), axis.title.y = element_textbox_simple( hjust = 0, orientation = "left-rotated", minwidth = unit(1, "in"), maxwidth = unit(2, "in"), padding = margin(4, 4, 2, 4), margin = margin(0, 0, 2, 0), fill = "lightsteelblue1" ) ) ``` ![](https://i.imgur.com/THCJtUW.png) Created on 2020-03-21 by the [reprex package](https://reprex.tidyverse.org) (v0.3.0)

I tried the following:

Expand reprex ``` r library(ggplot2) library(ggtext) library(dplyr) df <- iris %>% as_tibble() %>% select(Species, Sepal.Width) %>% mutate(Species = formattable::color_tile("pink", "lightblue")(Species)) %>% print() #> # A tibble: 150 x 2 #> Species Sepal.Width #> #> 1 " 2 " 3 " 4 " 5 " 6 " 7 " 8 " 9 " 10 " # … with 140 more rows df %>% ggplot(aes(Species, Sepal.Width)) + geom_boxplot() + theme( axis.text.x = element_markdown() ) ``` ![](https://i.imgur.com/KCrwI90.png) Created on 2020-03-21 by the [reprex package](https://reprex.tidyverse.org) (v0.3.0)

But nothing happens.. Is it possible to do somehow?

clauswilke commented 4 years ago

Sorry, no, this isn't currently supported. Maybe at some point in the future. Will require a complete rewrite of the rendering engine, though.

fmmattioni commented 4 years ago

Thanks for the quick reply! I will see if I can come up with a custom function.

clauswilke commented 3 years ago

Addressed in #53.

fmmattioni commented 3 years ago

Hi @clauswilke, I was taking a look at sinab now, and it looks so cool! Is it already possible to use this with ggplot2?

clauswilke commented 3 years ago

@fmmattioni With a bit of work, yes. I may add these instructions to the sinab web site: https://stackoverflow.com/a/63929139/4975218

fmmattioni commented 3 years ago

Thank you! This is so incredible! I am really looking forward to the official release! Thank you for this!

fmmattioni commented 3 years ago

Hi @clauswilke, just a follow up on this question: it seems that this still does not work in axis.text, any thoughts?

reprex:

library(ggplot2)
library(dplyr)
library(glue)
library(rlang)
library(sinab)  # remotes::install_github("clauswilke/sinab")

# helper code that will eventually live in the ggtext package
element_html <- function(css = NULL, family = NULL, face = NULL, size = NULL, colour = NULL, fill = NULL,
                         linetype = NULL, linewidth = NULL, hjust = NULL, vjust = NULL, lineheight = NULL,
                         margin = NULL, width = NULL, height = NULL, color = NULL, 
                         debug = FALSE, inherit.blank = FALSE) {
  if (!is.null(color))
    colour <- color

  # doesn't work with other values at this time
  hjust <- 0
  vjust <- 1

  structure(
    list(
      css = css,
      family = family, face = face, size = size, colour = colour, fill = fill,
      linetype = linetype, linewidth = linewidth, hjust = hjust, vjust = vjust,
      lineheight = lineheight, margin = margin, width = width, height = height,
      debug = debug, inherit.blank = inherit.blank),
    class = c("element_html", "element_text", "element")
  )
}

element_grob.element_html <- function(element, label = "", x = NULL, y = NULL,
                                      family = NULL, face = NULL, colour = NULL, size = NULL,
                                      hjust = NULL, vjust = NULL, lineheight = NULL,
                                      margin = NULL, ...) {
  if (is.null(label))
    return(ggplot2::zeroGrob())

  # for now we ignore hjust and vjust, it doesn't work yet
  hj <- 0
  vj <- 1

  css <- element$css %||% ""

  html_grob(
    label, x = x, y = y, hjust = hj, vjust = vj,
    width = element$width, height = element$height,
    css = css
  )
}

# CSS styling
css <- '
p { text-align: center; padding-top: 2px; }
.setosa { text-align: left; }
'

# plotting code
iris %>%
  mutate(
    # set class attribute to species name
    Species = glue('<p class = "{Species}">{Species}</p>')
  ) %>%
  ggplot(aes(x = Petal.Width, y = Species)) +
  geom_boxplot() +
  theme(axis.text.y = element_html(css = css))
#> Error in valid.viewport(x, y, width, height, just, gp, clip, xscale, yscale, : 'x', 'y', 'width', and 'height' must all be units of length 1

Created on 2020-10-21 by the reprex package (v0.3.0)

clauswilke commented 3 years ago

Yes, writing an element that can be used as axis text requires a little more work, because those elements need to be able to receive vectorized input. It's a solvable problem, but I don't have a solution ready to go at this time.

fmmattioni commented 3 years ago

Oh, I got it! Thank you!