我正在尝试一种可复制的方法来计算网页上图形的各种颜色的颜色对比度。我发现了以下功能:https://rdrr.io/github/m-clark/visibly/src/R/color_contrast_checker.R,这正是我想要的两种颜色之间的比较。
我希望能够给这个函数一个前景和背景颜色,这是可以循环使用的十六进制代码的有效列表,因此函数可以计算两个列表中所有颜色的所有组合的颜色对比度。我曾尝试在数据帧中给函数一个颜色列表,并使用for循环多次重复该函数,但没有成功。我认为该功能的设计不会超过1个元素,即1x前景和1x背景色,但我对R中的功能和循环有点新手。有人知道我如何实现这一点吗,谢谢?
以下是没有取得任何成功的示例代码:
library(gplots)
library(jsonlite)
library(dplyr)
background_col_list<-as.character(c("#6A86B8","#DFE3EB","#E57D3A","#BBB332"))
foreground_col_list<-as.character(c("#6A86B8","#DFE3EB","#E57D3A","#BBB332"))
result.df <- expand.grid(as.character(foreground_col_list),as.character(background_col_list))
result.df<-result.df %>%
mutate_all(as.character)
color_contrast_checker <- function(foreground, background) {
#initial checks
if ((is.null(foreground) | rlang::is_empty(foreground)) |
(is.null(background) | rlang::is_empty(background)))
stop('Need both foreground and background colors')
if (!is.character(foreground) | !is.character(background))
stop(strwrap('Elements must be character string as a named R color or
hex (e.g. "#ffffff")'))
#note: alpha returned by col2hex will be ignored
if (foreground %in% colors()){
foreground <- col2hex(foreground)
} else {
if (!nchar(foreground) %in% c(7, 9) | !grepl('^#', foreground))
stop(strwrap('foreground must be an R color, e.g. see colors(),
or a hex of the form #ff5500'))
}
if (background %in% colors()) {
background <- col2hex(background)
} else {
if (!nchar(background) %in% c(7, 9) | !grepl('^#', background))
stop(strwrap('background must be an R color, e.g. see colors(),
or a hex of the form #ff5500'))
}
#remove pound sign
foreground <- substr(foreground, start = 2, stop = nchar(foreground))
background <- substr(background, start = 2, stop = nchar(background))
url <- paste0('https://webaim.org/resources/contrastchecker/?fcolor=',
foreground,
'&bcolor=',
background,
'&api')
result <- suppressWarnings({readLines(url)})
if (!requireNamespace('jsonlite', quietly = TRUE)) {
result <- strsplit(
gsub(result, pattern = '\{|\}|"', replacement = ''),
',')
return(result[[1]])
}
data.frame(jsonlite::fromJSON(result))
}
for (value in result.df) {
color_contrast_checker(foreground=result.df$Var1, background=result.df$Var2) #Var1 & Var2 column names of result.df df that contains list of hex codes
}
#Have also tried:
for (i in 1:length(unique(background_col_list))) {
color_contrast_checker(background_col_list, foreground_col_list)
}
基R中最简单的选项是results = apply(result.df, 1, function(x) color_contrast_checker(x[1], x[2]))
,然后可以将其转换为更可读的输出(例如do.call(rbind, results)
(。
然而,这个功能有点慢——你可以在R.中很容易地自己实现检查
首先,我们检查W3C使用什么作为对比度:
对比度(L1+0.05(/(L2+0.05(,其中
- L1是颜色中较浅颜色的相对亮度,并且
- L2是颜色中较暗的颜色的相对亮度
然后我们检查W3C定义的相对亮度:
对于sRGB颜色空间,颜色的相对亮度定义为L=0.2126*R+0.7152*G+0.0722*B
所以在这一点上,你需要做的就是计算每种颜色的相对亮度,然后计算它们的比例,并检查它们是否通过了所需的任何阈值:
WCAG 2.0 AA级别要求普通文本的对比度至少为4.5:1,大型文本的对比率至少为3:1。WCAG 2.1要求图形和用户界面组件(例如表单输入边界(的对比度至少为3:1。WCAG AAA级要求普通文本的对比度至少为7:1,大型文本的对比率至少为4.5:1。
在代码中:
# Transform colors to RGB values, and RGB values to relative luminance
result.df$L_background = apply(col2rgb(result.df[,1]), 2, function(x)
0.2126 * x[1] + 0.7152 * x[2] + 0.0722 * x[3])
result.df$L_foreground = apply(col2rgb(result.df[,2]), 2, function(x)
0.2126 * x[1] + 0.7152 * x[2] + 0.0722 * x[3])
# Apply the contrast ratio formula (max luminance is brighter, min is darker)
result.df$L_ratio = apply(result.df[,3:4], 1, function(x)
(max(x) + 0.05)/(min(x) + 0.05))
# Check against standard thresholds
result.df$WCAG2_0_AA_pass = result.df$L_ratio > 4.5
result.df$WCAG2_1_pass = result.df$L_ratio > 3
result.df$WCAG_AAA_pass = result.df$L_ratio > 7
对于不太大的支票来说,这是相对较快的。某个地方可能存在矢量化解决方案。