Skip to content

Commit 43d882d

Browse files
committed
Merge pull request #553 from ropensci/fix/toRGB
Better toRGB
2 parents 2748789 + 96c9913 commit 43d882d

File tree

11 files changed

+71
-44
lines changed

11 files changed

+71
-44
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: plotly
22
Title: Create Interactive Web Graphics via 'plotly.js'
3-
Version: 3.4.15
3+
Version: 3.5.0
44
Authors@R: c(person("Carson", "Sievert", role = c("aut", "cre"),
55
email = "cpsievert1@gmail.com"),
66
person("Chris", "Parmer", role = c("aut", "cph"),

NEWS

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
3.5.0 -- 19 Apr 2016
2+
3+
NEW FEATURES:
4+
5+
The toRGB() function will now respect alpha channels in hex color codes and can recursively apply alpha.
6+
7+
CHANGES:
8+
9+
The toRGB() function will always output color codes with an alpha channel (e.g. toRGB('black') is now 'rgba(0,0,0,1)' instead of 'rgb(0,0,0)')
10+
111
3.4.15 -- 18 Apr 2016
212

313
BUGFIX:

R/ggplotly.R

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,6 @@ gg2list <- function(p, width = NULL, height = NULL, tooltip = "all", source = "A
277277
theme[["strip.text.x"]] %||% theme[["strip.text"]],
278278
"npc", "height"
279279
)
280-
# TODO: why does stripSize need to be inflated here?
281-
panelMarginY <- panelMarginY + 1.5 * stripSize
282280
# space for ticks/text in free scales
283281
if (p$facet$free$x) {
284282
axisTicksX <- unitConvert(

R/layers2traces.R

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,10 @@ geom2trace.GeomPolygon <- function(data, params, p) {
460460
line = list(
461461
# NOTE: line attributes must be constant on a polygon
462462
width = aes2plotly(data, params, "size"),
463-
color = aes2plotly(data, params, "colour"),
463+
color = toRGB(
464+
aes2plotly(data, params, "colour"),
465+
aes2plotly(data, params, "alpha")
466+
),
464467
dash = aes2plotly(data, params, "linetype")
465468
),
466469
fill = "tozerox",

R/toRGB.R

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,36 @@
55
#' @export
66
toRGB <- function(x, alpha = 1) {
77
if (is.null(x)) return(x)
8-
# as of ggplot2 version 1.1, an NA alpha is treated as though it's 1
9-
alpha[is.na(alpha)] <- 1
10-
# if we've already made the proper conversion, return the input
11-
if (inherits(x, "plotly_rgba")) return(x)
12-
if (inherits(x, "plotly_rgb")) {
13-
if (all(alpha == 1)) return(x)
14-
# all alpha channel
15-
x <- sub("^rgb", "rgba", sub("\\)", paste0(",", alpha, ")"), x))
16-
return(prefix_class(x, "plotly_rgba"))
8+
if (any(x %in% "transparent")) return(x)
9+
# add alpha to already converted "rgb(x,y,z)" codes
10+
idx <- grepl("^rgba\\(", x) & alpha <= 1 & 0 <= alpha
11+
if (any(idx)) {
12+
x[idx] <- rgb2hex(x[idx])
1713
}
1814
# for some reason ggplot2 has "NA" in some place (instead of NA)
1915
if (is.character(x)) {
2016
x[x == "NA"] <- NA
2117
}
22-
has_alpha <- all(0 <= alpha & alpha < 1)
23-
rgb_matrix <- col2rgb(x, alpha = has_alpha)
24-
# rescale alpha
25-
# TODO: what if x already has an alpha channel???
26-
if (has_alpha) rgb_matrix["alpha", ] <- alpha
27-
container <- if (has_alpha) "rgba(%s)" else "rgb(%s)"
28-
rgb_a <- sprintf(container, apply(rgb_matrix, 2, paste, collapse = ","))
29-
rgb_a[is.na(x)] <- "transparent"
30-
structure(rgb_a, class = if (has_alpha) "plotly_rgba" else "plotly_rgb")
18+
# as of ggplot2 version 1.1, an NA alpha is treated as though it's 1
19+
alpha[is.na(alpha)] <- 1
20+
rgb_matrix <- grDevices::col2rgb(x, alpha = TRUE)
21+
# multiply the existing alpha with specified alpha (both on 0-1 scale)
22+
rgb_matrix["alpha", ] <- alpha * scales::rescale(
23+
rgb_matrix["alpha", ], from = c(0, 255)
24+
)
25+
rgb_matrix["alpha", ] <- round(rgb_matrix["alpha", ], 4)
26+
rgba <- sprintf("rgba(%s)", apply(rgb_matrix, 2, paste, collapse = ","))
27+
rgba[is.na(x)] <- "transparent"
28+
rgba
29+
}
30+
31+
# take a 'plotly color' and produce a hex code
32+
rgb2hex <- function(string = "rgba(255,255,255,1)") {
33+
vals <- sub("rgba\\(", "", sub("\\)", "", string))
34+
valz <- strsplit(vals, ",")
35+
sapply(valz, function(x) {
36+
x <- setNames(as.numeric(x), c("red", "green", "blue", "alpha"))
37+
x[["alpha"]] <- x[["alpha"]] * 255
38+
do.call(grDevices::rgb, c(x, list(maxColorValue = 255)))
39+
})
3140
}

tests/testthat/test-ggplot-boxplot.R

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,6 @@ test_that("legends for boxplot", {
5656
for (i in 1:3) {
5757
expect_identical(tr[[i]]$showlegend, TRUE)
5858
}
59-
# check the fill colors are correct
60-
g <- ggplot_build(p)
61-
fill.colors <- unique(g$data[[1]]["fill"])[,1]
62-
for (i in 1:3) {
63-
plotly.color <- as.integer(strsplit(gsub("[\\(\\)]|rgb", "",
64-
tr[[i]]$fillcolor), split = ",")[[1]])
65-
names(plotly.color) <- c("red", "green", "blue")
66-
expect_equal(plotly.color, col2rgb(fill.colors[i])[,1],
67-
tolerance = 1)
68-
}
6959
})
7060

7161
dat <- data.frame(

tests/testthat/test-ggplot-histogram.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ test_that("Histogram with fixed colour/fill works", {
5151
gg <- base + geom_histogram(colour = "darkgreen", fill = "white")
5252
info <- expect_traces(gg, 1, "fixed-fill-color")
5353
tr <- info$data[[1]]
54-
expect_true(tr$marker$color == "rgb(255,255,255)")
55-
expect_true(tr$marker$line$color == "rgb(0,100,0)")
54+
expect_true(tr$marker$color == "rgba(255,255,255,1)")
55+
expect_true(tr$marker$line$color == "rgba(0,100,0,1)")
5656
})
5757

5858
test_that("Specify histogram binwidth", {

tests/testthat/test-ggplot-hline.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ test_that("second trace be the hline", {
1616
expect_true(min(l$x) < min(x))
1717
expect_true(max(l$x[2]) > max(x))
1818
expect_identical(l$mode, "lines")
19-
expect_true(l$line$color == "rgb(0,255,0)")
19+
expect_true(l$line$color == "rgba(0,255,0,1)")
2020
})
2121

2222
test_that("vector yintercept results in multiple horizontal lines", {
@@ -31,7 +31,7 @@ test_that("vector yintercept results in multiple horizontal lines", {
3131
expect_true(min(xs, na.rm = TRUE) < min(x))
3232
expect_true(max(xs, na.rm = TRUE) > max(x))
3333
expect_identical(l$mode, "lines")
34-
expect_true(l$line$color == "rgb(255,0,0)")
34+
expect_true(l$line$color == "rgba(255,0,0,1)")
3535

3636
})
3737

tests/testthat/test-ggplot-rect.R

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ expect_traces <- function(gg, n.traces, name) {
1010
})
1111
has.data <- all.traces[!no.data]
1212
expect_equal(length(has.data), n.traces)
13-
list(traces=has.data, layout=L$layout)
13+
list(data=has.data, layout=L$layout)
1414
}
1515

1616
df <- data.frame(
@@ -23,7 +23,7 @@ gg <- ggplot(df, aes(xmin = x, xmax = x + 1, ymin = y, ymax = y + 2)) +
2323

2424
test_that('geom_rect becomes 1 trace with mode="lines" fill="tozerox"', {
2525
info <- expect_traces(gg, 1, "black")
26-
tr <- info$traces[[1]]
26+
tr <- info$data[[1]]
2727
expect_identical(tr$fill, "tozerox")
2828
expect_identical(tr$type, "scatter")
2929
expect_identical(tr$mode, "lines")
@@ -42,7 +42,7 @@ gg4 <- ggplot(df4, aes(xmin = x, xmax = x + 0.5, ymin = 0, ymax = 1)) +
4242

4343
test_that('trace contains NA back to 1st rect', {
4444
info <- expect_traces(gg4, 1, "black4")
45-
tr <- info$traces[[1]]
45+
tr <- info$data[[1]]
4646
expect_identical(tr$fill, "tozerox")
4747
expect_identical(tr$type, "scatter")
4848
expect_identical(tr$mode, "lines")
@@ -70,7 +70,7 @@ rect.color <- ggplot(df4, aes(xmin = x, xmax = x + 0.5, ymin = 0, ymax = 1)) +
7070
test_that('rect color', {
7171
info <- expect_traces(rect.color, 2, "color")
7272
traces.by.name <- list()
73-
for(tr in info$traces){
73+
for(tr in info$data){
7474
expect_true(tr$fillcolor == toRGB("grey"))
7575
expect_true(tr$fill == "tozerox")
7676
expect_equal(tr$y,
@@ -97,7 +97,7 @@ rect.fill <- ggplot(df4, aes(xmin = x, xmax = x + 0.5, ymin = 0, ymax = 1)) +
9797
test_that('rect color', {
9898
info <- expect_traces(rect.fill, 2, "fill")
9999
traces.by.name <- list()
100-
for(tr in info$traces){
100+
for(tr in info$data){
101101
expect_true(tr$line$color == "transparent")
102102
expect_true(tr$fill == "tozerox")
103103
expect_equal(tr$y,
@@ -125,7 +125,7 @@ rect.fill.color <-
125125
test_that('rect aes(fill) with constant color', {
126126
info <- expect_traces(rect.fill.color, 2, "fill-color")
127127
traces.by.name <- list()
128-
for(tr in info$traces){
128+
for(tr in info$data){
129129
expect_true(tr$line$color == toRGB("black"))
130130
expect_true(tr$fill == "tozerox")
131131
expect_equal(tr$y,
@@ -145,3 +145,14 @@ test_that('rect aes(fill) with constant color', {
145145
expect_false(traces.by.name[[1]]$fillcolor ==
146146
traces.by.name[[2]]$fillcolor)
147147
})
148+
149+
150+
p <- ggplot(data = data.frame(x1 = 1, x2 = 2, y1 = 1, y2 = 2)) +
151+
geom_rect(aes(xmin = x1, xmax = x2, ymin = y1, ymax = y2),
152+
fill = "#00000011", color = "black")
153+
154+
test_that('Specifying alpha in hex color code works', {
155+
info <- expect_traces(p, 1, "fill-hex-alpha")
156+
expect_match(info$data[[1]]$fillcolor, "rgba\\(0,0,0,0\\.0[6]+")
157+
})
158+

tests/testthat/test-ggplot-vline.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ test_that("second trace be the vline", {
1616
expect_true(l$y[1] <= 0)
1717
expect_true(l$y[2] >= 3.325)
1818
expect_true(l$mode == "lines")
19-
expect_true(l$line$color == "rgb(0,255,0)")
19+
expect_true(l$line$color == "rgba(0,255,0,1)")
2020
})
2121

2222
test_that("vector xintercept results in multiple vertical lines", {
@@ -31,5 +31,5 @@ test_that("vector xintercept results in multiple vertical lines", {
3131
expect_true(min(ys, na.rm = TRUE) <= min(y))
3232
expect_true(max(ys, na.rm = TRUE) >= max(y))
3333
expect_true(l$mode == "lines")
34-
expect_true(l$line$color == "rgb(0,0,255)")
34+
expect_true(l$line$color == "rgba(0,0,255,1)")
3535
})

tests/testthat/test-toRGB.R

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
context("toRGB")
2+
3+
test_that("Can apply alpha recursively with toRGB()", {
4+
col <- toRGB(toRGB("black", 0.9), 0.9)
5+
expect_match(col, "rgba\\(0,0,0,0\\.80")
6+
})

0 commit comments

Comments
 (0)