0

How does colour contrasting in R work? I'd assume there is some trigger in the colour hex values that can be used to help tell whether one should change colour for a label to something lighter/darker. I'm interested in a general solution - I know there are packages that do go colour contrast controls for ggplot2. I'd more like an approach that I can control the degree of colour contrasts.

This code illustrates the point. The scales package handles colour contrast great. I would just like to have some more control over it.

 library(tidyverse)

    library(scales)

    show_col(c("darkred", 
               "wheat", 
               "darkblue", 
               "steelblue"))



tibble(key = letters[1:4], 
       value = 1:4) %>%
  ggplot(aes(key, value))+
  geom_col(aes(fill = key))+
  geom_text(aes(label = key), 
            position = position_stack(vjust = 0.5))+
  scale_fill_manual(values = c("darkred", 
                           "wheat", 
                           "darkblue", 
                           "steelblue")) 

From scales from scales code

From ggplot from ggplot graphic

elliot
  • 1,844
  • 16
  • 45
  • Related: [Contrast between label and background: determine if color is light or dark](https://stackoverflow.com/questions/49437263/contrast-between-label-and-background-determine-if-color-is-light-or-dark); [Text color based on contrast against background](https://stackoverflow.com/questions/47281365/text-color-based-on-contrast-against-background); [Changing background color for a text annotation to increase contrast and visibility](https://stackoverflow.com/questions/39602828/changing-background-color-for-a-text-annotation-to-increase-contrast-and-visibil) – Henrik Feb 28 '21 at 19:15
  • Because you seemed to like the `show_cols` function, you may check the [code for the label colors](https://github.com/r-lib/scales/blob/master/R/colour-manip.r#L110-L112). Not too complicated. – Henrik Feb 28 '21 at 19:36

1 Answers1

1

@Henrik pointed out that the magic of open-source means I can get and build upon the code from the scales package to accomplish my goals.

library(tidyverse)
library(scales)

# Create colour vector
colours <- c("steelblue", 
  "wheat", 
  "darkblue", 
  "darkred") 


### Code from scales package use switch from white/black based on colour specification

## grab matrx of hcl. According to ?hcl, 
## stands for hue, chroma and luminance
hcl <- farver::decode_colour(
  colours, "rgb", "hcl")

## Simple ifelse statement to create binary 
## colour vector based on conditional value
## of luminance that is higher than 50. 
label_col <- ifelse(hcl[, "l"] > 50, "black", "white")


## back to ggplot2 example


## 1) Use borrowed scales code to create a 
## simple wrapper function called contraster
contraster <- function(.colours){
  
  .colurs_hcl <-  farver::decode_colour(
    .colours, "rgb", "hcl")

  ifelse(.colurs_hcl[, "l"] > 50, "black", "white")
}

colours <- c("steelblue", 
             "wheat", 
             "darkblue", 
             "darkred") 

# 2) Now re-create the data and plot
tibble(key = letters[1:4], 
       value = 1:4) %>%
  ggplot(aes(key, value))+
  geom_col(aes(fill = key))+
  geom_text(aes(label = key),
            color = contraster(colours),
            position = 
              position_stack(vjust = 0.5))+
  scale_fill_manual(values = colours) +
  labs(title = "Label colours are now contrasting with the background")

enter image description here

elliot
  • 1,844
  • 16
  • 45