Skip to content

Commit 7ee6c75

Browse files
committed
size now sets default error_[x/y].width and span sets error_[x/y].thickness; closes #1226
1 parent 88bc317 commit 7ee6c75

File tree

5 files changed

+75
-21
lines changed

5 files changed

+75
-21
lines changed

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
* The `color` argument now maps to `fillcolor`, making it much easier to use polygon fills to encode data values (e.g., choropleth maps). For backwards-compatibilty reasons, when `color` maps to `fillcolor`, `alpha` defaults to 0.5 (instead of 1). For an example, `plot_mapbox(mn_res, color = ~INDRESNAME)` or `plot_mapbox(mn_res, split = ~INDRESNAME, color = ~AREA, showlegend = FALSE, stroke = I("black"))`.
1515
* The `color` argument no longer automatically add `"markers"` to the `mode` attribute for scatter/scattergl trace types. Those who wish to have the old behavior back, should add `"markers"` to the `mode` explicity (e.g., change `plot_ly(economics, x = ~pce, y = ~pop, color = ~as.numeric(date), mode = "lines")` to `plot_ly(economics, x = ~pce, y = ~pop, color = ~as.numeric(date), mode = "lines+markers")`).
16+
* The `size` argument now informs a default [error_[x/y].width](https://plot.ly/r/reference/#scatter-error_x-width) (and `span` informs [error_[x/y].thickness](https://plot.ly/r/reference/#scatter-error_x-thickness)). Note you can override the default by specifying directly (e.g. `plot_ly(x = 1:10, y = 1:10, size = I(10), error_x = list(value = 5, width = 0))`)
1617
* `layout.showlegend` now defaults to `TRUE` for a *single* pie trace. This is a more sensible default and matches pure plotly.js behavior.
1718
* The `elementId` field is no longer populated, which fixes the "Ignoring explicitly provided widget ID" warning in shiny applications (see #985).
1819

R/plotly.R

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,16 @@
5353
#' @param linetypes A character vector of `lty` values or [dash names](https://plot.ly/r/reference#scatter-line-dash)
5454
#' @param size (Numeric) values mapped to relevant 'fill-size' attribute(s)
5555
#' (e.g., [marker.size](https://plot.ly/r/reference#scatter-marker-size),
56-
#' [textfont.size](https://plot.ly/r/reference#scatter-textfont-size), etc).
56+
#' [textfont.size](https://plot.ly/r/reference#scatter-textfont-size),
57+
#' and [error_x.width](https://plot.ly/r/reference#scatter-error_x-width)).
5758
#' The mapping from data values to symbols may be controlled using
5859
#' `sizes`, or avoided altogether via [I()] (e.g., `size = I(30)`).
5960
#' @param sizes A numeric vector of length 2 used to scale `size` to pixels.
6061
#' @param span (Numeric) values mapped to relevant 'stroke-size' attribute(s)
61-
#' (e.g., [marker.line.width](https://plot.ly/r/reference#scatter-marker-line-width))
62+
#' (e.g.,
63+
#' [marker.line.width](https://plot.ly/r/reference#scatter-marker-line-width),
64+
#' [line.width](https://plot.ly/r/reference#scatter-line-width) for filled polygons,
65+
#' and [error_x.thickness](https://plot.ly/r/reference#scatter-error_x-thickness))
6266
#' The mapping from data values to symbols may be controlled using
6367
#' `spans`, or avoided altogether via [I()] (e.g., `span = I(30)`).
6468
#' @param spans A numeric vector of length 2 used to scale `span` to pixels.

R/plotly_build.R

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -564,18 +564,29 @@ map_size <- function(traces, stroke = FALSE) {
564564
isSingular <- length(size_) == 1
565565
attrs <- Schema$traces[[type]]$attributes
566566

567+
# `span` controls marker.line.width
567568
if (has_attr(type, "marker")) {
568569
s <- if (isSingular) size_ else if (array_ok(attrs$marker$line$width)) sizes
569570
trace$marker$line <- modify_list(list(width = default(s)), trace$marker$line)
570571
}
572+
573+
# `span` controls error_[x/y].thickness
574+
for (attr in c("error_y", "error_x")) {
575+
if (!has_attr(type, attr)) next
576+
s <- if (isSingular) size_ else if (array_ok(attrs[[attr]]$thickness)) sizes
577+
trace[[attr]] <- modify_list(list(thickness = default(s)), trace[[attr]])
578+
}
579+
580+
# When fill exists, `span` controls line.width
571581
if (has_fill(trace) && has_attr(type, "line")) {
572-
s <- if (isSingular) size_ else if (array_ok(attrs$line$width)) sizes
573-
if (is.null(s)) {
582+
s <- if (isSingular) size_ else if (array_ok(attrs$line$width)) sizes else NA
583+
if (is.na(s)) {
574584
warning("`line.width` does not currently support multiple values.", call. = FALSE)
575585
} else {
576586
trace[["line"]] <- modify_list(list(width = default(s)), trace[["line"]])
577587
}
578588
}
589+
579590
trace
580591
},
581592
size = function(trace, sizes) {
@@ -584,30 +595,34 @@ map_size <- function(traces, stroke = FALSE) {
584595
isSingular <- length(size_) == 1
585596
attrs <- Schema$traces[[type]]$attributes
586597

587-
# size controls marker.size (note 'bar' traces have marker but not marker.size)
598+
# `size` controls marker.size (note 'bar' traces have marker but not marker.size)
588599
# TODO: always ensure an array? https://github.com/ropensci/plotly/pull/1176
589600
if (has_attr(type, "marker") && "size" %in% names(attrs$marker)) {
590601
s <- if (isSingular) size_ else if (array_ok(attrs$marker$size)) sizes
591602
trace$marker <- modify_list(list(size = default(s), sizemode = default("area")), trace$marker)
592603
}
593604

594-
# size controls textfont.size
605+
# `size` controls textfont.size
595606
if (has_attr(type, "textfont")) {
596607
s <- if (isSingular) size_ else if (array_ok(attrs$textfont$size)) sizes
597608
trace$textfont <- modify_list(list(size = default(s)), trace$textfont)
598609
}
599610

600-
# TODO: should size set error_x.value?
601-
#for (attr in c("error_y", "error_x")) {
602-
# if (!has_attr(type, attr)) next
603-
# s <- if (isSingular) size_ else if (array_ok(attrs[[attr]]$width)) sizes
604-
# trace[[attr]] <- modify_list(list(width = default(s)), trace[[attr]])
605-
#}
611+
# `size` controls error_[x/y].width
612+
for (attr in c("error_y", "error_x")) {
613+
if (!has_attr(type, attr)) next
614+
s <- if (isSingular) size_ else if (array_ok(attrs[[attr]]$width)) sizes
615+
trace[[attr]] <- modify_list(list(width = default(s)), trace[[attr]])
616+
}
606617

607-
# if fill does not exist, size controls line.width
618+
# if fill does not exist, `size` controls line.width
608619
if (!has_fill(trace) && has_attr(type, "line")) {
609-
s <- if (isSingular) size_ else if (array_ok(attrs$line$color)) sizes
610-
trace[["line"]] <- modify_list(list(width = default(s)), trace[["line"]])
620+
s <- if (isSingular) size_ else if (array_ok(attrs$line$width)) sizes else NA
621+
if (is.na(s)) {
622+
warning("`line.width` does not currently support multiple values.", call. = FALSE)
623+
} else {
624+
trace[["line"]] <- modify_list(list(width = default(s)), trace[["line"]])
625+
}
611626
}
612627
trace
613628
}
@@ -692,23 +707,33 @@ map_color <- function(traces, stroke = FALSE, title = "", colorway, na.color = "
692707
attrs <- Schema$traces[[type]]$attributes
693708
default_ <- if (is_colorway) function(x) prefix_class(default(x), "colorway") else default
694709

710+
# `color` controls marker.color, textfont.color, error_[x/y].color
695711
# TODO: any more attributes that make sense to include here?
696712
for (attr in c("marker", "textfont", "error_y", "error_x")) {
697713
if (!has_attr(type, attr)) next
698714
if (is_colorway && "textfont" == attr) next
699-
col <- if (isSingular) rgba_ else if (array_ok(attrs[[attr]]$color)) rgba
700-
trace[[attr]] <- modify_list(list(color = default_(col)), trace[[attr]])
715+
col <- if (isSingular) rgba_ else if (array_ok(attrs[[attr]]$color)) rgba else NA
716+
if (is.na(col)) {
717+
warning("`", attr, ".color` does not currently support multiple values.", call. = FALSE)
718+
} else {
719+
trace[[attr]] <- modify_list(list(color = default_(col)), trace[[attr]])
720+
}
701721
}
702722

723+
# If trace has fill, `color` controls fillcolor; otherwise line.color
703724
if (has_fill(trace)) {
704725
if (!isSingular) warning("Only one fillcolor per trace allowed", call. = FALSE)
705726
# alpha defaults to 0.5 when applied to fillcolor
706727
if (is.null(trace[["alpha"]])) rgba_ <- toRGB(rgba_, 0.5)
707728
if (isSingular) trace <- modify_list(list(fillcolor = default_(rgba_)), trace)
708729
} else if (has_attr(type, "line")) {
709730
# if fill does not exist, 'color' controls line.color
710-
col <- if (isSingular) rgba_ else if (array_ok(attrs$line$color)) rgba
711-
trace[["line"]] <- modify_list(list(color = default_(col)), trace[["line"]])
731+
col <- if (isSingular) rgba_ else if (array_ok(attrs$line$color)) rgba else NA
732+
if (is.na(col)) {
733+
warning("`line.color` does not currently support multiple values.", call. = FALSE)
734+
} else {
735+
trace[["line"]] <- modify_list(list(color = default_(col)), trace[["line"]])
736+
}
712737
}
713738
trace
714739
}

man/plot_ly.Rd

Lines changed: 6 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-plotly.R

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,23 @@ test_that("Complex example works", {
189189

190190
l <- expect_traces(p, 3, "time-series-summary")
191191
})
192+
193+
194+
test_that("span/size controls errorbar thickness/width", {
195+
196+
p <- plot_ly(x = 1:10, y = 1:10, error_x = list(value = 3), error_y = list(value = 2), span = I(5), size = I(10), stroke = I("black"), color = I("red")) %>%
197+
plotly_build()
198+
199+
d <- p$x$data
200+
expect_length(d, 1)
201+
202+
expect_true(d[[1]]$error_x$value == 3)
203+
expect_true(d[[1]]$error_x$thickness == 5)
204+
expect_true(d[[1]]$error_x$width == 10)
205+
expect_true(d[[1]]$error_x$color == toRGB("red"))
206+
207+
expect_true(d[[1]]$error_y$value == 2)
208+
expect_true(d[[1]]$error_y$thickness == 5)
209+
expect_true(d[[1]]$error_y$width == 10)
210+
expect_true(d[[1]]$error_y$color == toRGB("red"))
211+
})

0 commit comments

Comments
 (0)