Skip to content

Commit 61b5095

Browse files
committed
merge conflicts
2 parents fbc5114 + 0ea2892 commit 61b5095

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+625
-150
lines changed

DESCRIPTION

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@ Suggests:
6868
rgeos,
6969
png,
7070
IRdisplay,
71-
processx
71+
processx,
72+
plotlyGeoAssets,
73+
rstudioapi,
74+
forcats
7275
LazyData: true
7376
RoxygenNote: 6.0.1.9000
7477
Encoding: UTF-8

NAMESPACE

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ S3method(to_basic,default)
8181
S3method(transmute_,plotly)
8282
S3method(ungroup,plotly)
8383
export("%>%")
84+
export(TeX)
8485
export(add_annotations)
8586
export(add_area)
8687
export(add_bars)
@@ -104,6 +105,7 @@ export(add_scattergeo)
104105
export(add_segments)
105106
export(add_sf)
106107
export(add_surface)
108+
export(add_table)
107109
export(add_text)
108110
export(add_trace)
109111
export(animation_button)
@@ -141,6 +143,7 @@ export(hide_colorbar)
141143
export(hide_guides)
142144
export(hide_legend)
143145
export(highlight)
146+
export(highlight_key)
144147
export(knit_print.api_grid)
145148
export(knit_print.api_grid_local)
146149
export(knit_print.api_plot)

NEWS.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
### plotly.js and `plot_ly()` specific improvements
66

7-
* Upgraded to plotly.js v1.38.2. A _huge_ amount of features and improvements have been made since v1.29.2 (i.e., the version included in the last CRAN release of the R package - v4.7.1). Highlights include a complete re-write of `scattergl` to make it nearly feature complete with `scatter`, localization of text rendering (i.e., international translations), and six new trace types (`cone`, `scatterpolar`, `scatterpolargl`, `splom`, `table`, & `violin`)! See [here](https://github.com/plotly/plotly.js/releases) for a complete list of plotly.js-specific improvements.
7+
* Upgraded to plotly.js v1.38.3. A _huge_ amount of features and improvements have been made since v1.29.2 (i.e., the version included in the last CRAN release of the R package - v4.7.1). Highlights include a complete re-write of `scattergl` to make it nearly feature complete with `scatter`, localization of text rendering (i.e., international translations), and six new trace types (`cone`, `scatterpolar`, `scatterpolargl`, `splom`, `table`, & `violin`)! See [here](https://github.com/plotly/plotly.js/releases) for a complete list of plotly.js-specific improvements.
88
* Support for **sf** (simple feature) data structures was added to `plot_ly()`, `plot_mapbox()`, and `plot_geo()` (via the new `add_sf()` function). See [this blog post](https://blog.cpsievert.me/2018/03/30/visualizing-geo-spatial-data-with-sf-and-plotly) for an overview.
99
* Better control over the stroke (i.e., outline) appearance of various filled graphical marks via the new "special arguments" (`stroke`, `strokes`, `alpha_stroke`, `span`, and `spans`). For an overview, see the **sf** blog post linked to in the bullet point above and the new package demos (list all demos with `demo(package = "plotly")`).
1010

@@ -15,13 +15,16 @@
1515

1616
### Other improvements relevant for all **plotly** objects
1717

18+
* LaTeX rendering via MathJax is now supported and the new `TeX()` function may be used to flag a character vector as LaTeX (#375). Use the new `mathjax` argument in `config()` to specify either external (`mathjax="cdn"`) or local (`mathjax="local"`) MathJaX. If `"cdn"`, mathjax is loaded externally (meaning an internet connection is needed for TeX rendering). If `"local"`, the PLOTLY_MATHJAX_PATH environment variable must be set to the location (a local file path) of MathJax. IMPORTANT: **plotly** uses SVG-based mathjax rendering which doesn't play nicely with HTML-based rendering (e.g., **rmarkdown** documents and **shiny** apps). To leverage both types of rendering, you must `<iframe>` your plotly graph(s) into the larger document (see [here](https://github.com/ropensci/plotly/blob/master/inst/examples/rmd/MathJax/index.Rmd) for an **rmarkdown** example and [here](https://github.com/ropensci/plotly/blob/master/inst/examples/rmd/MathJax/index.Rmd) for a **shiny** example).
1819
* The selection (i.e., linked-brushing) mode can now switch from 'transient' to 'persistent' by holding the 'shift' key. It's still possible to _force_ persistent selection by setting `persistent = TRUE` in `highlight()`, but `persistent = FALSE` (the default) is now recommended since it allows one to switch between [persistent/transient selection](https://plotly-book.cpsievert.me/linking-views-without-shiny.html#transient-versus-persistent-selection) in the browser, rather than at the command line.
1920
* The `highlight()` function gains a `debounce` argument for throttling the rate at which `on` events may be fired. This is mainly useful for improving user experience when `highlight(on = "plotly_hover")` and mousing over relevant markers at a rapid rate (#1277)
2021
* The new `partial_bundle()` function makes it easy to leverage [partial bundles of plotly.js](https://github.com/plotly/plotly.js#partial-bundles) for reduced file sizes and faster render times.
2122
* The `config()` function gains a `locale` argument for easily changing localization defaults (#1270). This makes it possible localize date axes, and in some cases, modebar buttons (#1270).
23+
* The `plot_geo()` function gains a `offline` argument for rendering `"scattergeo"` traces with or without an internet connection (#356). Leveraging this argument requires the new **plotlyGeoAssets** package.
24+
* Support for async rendering of inside **shiny** apps using the [promises](https://rstudio.github.io/promises/) package (#1209). For an example, run `plotly_example("shiny", "async")`.
2225
* Instead of an error, `ggplotly(NULL, "message")` and `plotly_build(NULL, "message")` now returns `htmltools::div("message")`, making it easier to relay messages in shiny when data isn't yet ready to plot (#1116).
2326
* The `animation_button()` function gains a `label` argument, making it easier to control the label of an animation button generated through the `frame` API (#1205).
24-
* Support for async rendering of inside **shiny** apps using the [promises](https://rstudio.github.io/promises/) package (#1209).
27+
* The new `highlight_key()` function provides a wrapper around `crosstalk::SharedData$new()`, making it easier to teach others how to leverage `SharedData` objects with **plotly** and **crosstalk**.
2528

2629
## CHANGES
2730

@@ -35,6 +38,7 @@
3538

3639
### Other changes relevant for all **plotly** objects
3740

41+
* All axis objects now default to `automargin = TRUE`. The majority of the time this should make axis labels more readable, but may have un-intended consequences in some rare cases (#1252).
3842
* The `elementId` field is no longer populated, which fixes the "Ignoring explicitly provided widget ID" warning in shiny applications (#985).
3943

4044
## BUG FIXES
@@ -52,6 +56,7 @@
5256

5357
### Other fixes relevant for all **plotly** objects
5458

59+
* Marker sizes (i.e., `marker.size`) are now _always_ based on the area when `marker.sizemode='area'` (which is the default sizemode when using the `size` argument). Previously, traces with one just one value supplied to `marker.size` were being sized by their diameter (#1133).
5560
* Bug fix for linking views with crosstalk where the source of the selection is an aggregated trace (#1218).
5661
* Resizing behavior, after updating `height`/`width` via **shiny** reactive values, is now correct (#1068).
5762
* Fixed algorithm for coercing the proposed layout to the plot schema (#1156).

R/add.R

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,38 @@ add_sf <- function(p, ..., x = ~x, y = ~y, data = NULL, inherit = TRUE) {
273273
}
274274

275275

276+
#' @inheritParams add_trace
277+
#' @param rownames whether or not to display the rownames of `data`.
278+
#' @rdname add_trace
279+
#' @export
280+
#' @examples
281+
#'
282+
#' plot_ly(economics) %>%
283+
#' add_table()
284+
add_table <- function(p, ..., rownames = TRUE, data = NULL, inherit = TRUE) {
285+
attrs <- list(...)
286+
dat <- plotly_data(add_data(p, data))
287+
if (is.data.frame(dat)) {
288+
vals <- lapply(names(dat), function(x) list(x))
289+
if (isTRUE(rownames)) vals <- c(list(""), vals)
290+
header_defaults <- list(
291+
values = vals,
292+
align = "right"
293+
)
294+
vals <- setNames(as.list(dat), NULL)
295+
if (isTRUE(rownames)) vals <- c(list(row.names(dat)), vals)
296+
cell_defaults <- list(
297+
values = vals,
298+
align = "right"
299+
)
300+
attrs$header <- modify_list(header_defaults, attrs$header)
301+
attrs$cells <- modify_list(cell_defaults, attrs$cells)
302+
}
303+
304+
do.call(add_trace_classed, c(list(p = p, class = "plotly_table", type = "table"), attrs))
305+
}
306+
307+
276308
#' @inheritParams add_trace
277309
#' @rdname add_trace
278310
#' @export

R/ggplotly.R

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@
4747
#' ggplotly(viz, tooltip = c("text", "size"))
4848
#'
4949
#' # linked scatterplot brushing
50-
#' library(crosstalk)
51-
#' d <- SharedData$new(mtcars)
50+
#' d <- highlight_key(mtcars)
5251
#' qplot(data = d, x = mpg, y = wt) %>%
5352
#' subplot(qplot(data = d, x = mpg, y = vs)) %>%
5453
#' layout(title = "Click and drag to select points") %>%
@@ -59,7 +58,7 @@
5958
#' demo("crosstalk-highlight-ggplotly", package = "plotly")
6059
#'
6160
#' # client-side linked brushing in a scatterplot matrix
62-
#' SharedData$new(iris) %>%
61+
#' highlight_key(iris) %>%
6362
#' GGally::ggpairs(aes(colour = Species), columns = 1:4) %>%
6463
#' ggplotly(tooltip = c("x", "y", "colour")) %>%
6564
#' highlight("plotly_selected")

R/highlight.R

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,8 @@
5757
#' # These examples are designed to show you how to highlight/brush a *single*
5858
#' # view. For examples of multiple linked views, see `demo(package = "plotly")`
5959
#'
60-
#'
6160
#' library(crosstalk)
62-
#' d <- SharedData$new(txhousing, ~city)
61+
#' d <- highlight_key(txhousing, ~city)
6362
#' p <- ggplot(d, aes(date, median, group = city)) + geom_line()
6463
#' gg <- ggplotly(p, tooltip = "city")
6564
#' highlight(gg, dynamic = TRUE)

R/layout.R

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,33 +91,47 @@ rangeslider <- function(p, start = NULL, end = NULL, ...) {
9191
#' @param collaborate include the collaborate mode bar button (unique to the R pkg)?
9292
#' @param cloud include the send data to cloud button?
9393
#' @param locale locale to use. See [here](https://github.com/plotly/plotly.js/tree/master/dist#to-include-localization) for more info.
94+
#' @param mathjax add [MathJax rendering support](https://github.com/plotly/plotly.js/tree/master/dist#to-support-mathjax).
95+
#' If `"cdn"`, mathjax is loaded externally (meaning an internet connection is needed for
96+
#' TeX rendering). If `"local"`, the PLOTLY_MATHJAX_PATH environment variable must be
97+
#' set to the location (a local file path) of MathJax. IMPORTANT: **plotly** uses SVG-based
98+
#' mathjax rendering which doesn't play nicely with HTML-based rendering
99+
#' (e.g., **rmarkdown** documents and **shiny** apps). To leverage both types of rendering,
100+
#' you must `<iframe>` your plotly graph(s) into the larger document
101+
#' (see [here](https://github.com/ropensci/plotly/blob/master/inst/examples/rmd/MathJax/index.Rmd)
102+
#' for an **rmarkdown** example and
103+
#' [here](https://github.com/ropensci/plotly/blob/master/inst/examples/rmd/MathJax/index.Rmd) for a **shiny** example).
94104
#' @author Carson Sievert
95105
#' @export
96106
#' @examples
97107
#'
108+
#' # remove the plotly logo and collaborate button from modebar
109+
#' config(plot_ly(), displaylogo = FALSE, collaborate = FALSE)
110+
#'
111+
#' # enable mathjax
112+
#' # see more examples at https://plot.ly/r/LaTeX/
113+
#' plot_ly(x = c(1, 2, 3, 4), y = c(1, 4, 9, 16)) %>%
114+
#' layout(title = TeX("\\text{Some mathjax: }\\alpha+\\beta x")) %>%
115+
#' config(mathjax = "cdn")
116+
#'
117+
#' # change the language used to render date axes and on-graph text
118+
#' # (e.g., modebar buttons)
98119
#' today <- Sys.Date()
99120
#' x <- seq.Date(today, today + 360, by = "day")
100121
#' p <- plot_ly(x = x, y = rnorm(length(x))) %>%
101122
#' add_lines()
102123
#'
103-
#' # remove the plotly logo and collaborate button from modebar
104-
#' config(p, displaylogo = FALSE, collaborate = FALSE)
105-
#'
106124
#' # japanese
107125
#' config(p, locale = "ja")
108126
#' # german
109127
#' config(p, locale = "de")
110-
#' # swiss-german
111-
#' config(p, locale = "de-CH")
112128
#' # spanish
113129
#' config(p, locale = "es")
114-
#' # french
115-
#' config(p, locale = "fr")
116130
#' # chinese
117131
#' config(p, locale = "zh-CN")
118132
#'
119133

120-
config <- function(p, ..., collaborate = TRUE, cloud = FALSE, locale = NULL) {
134+
config <- function(p, ..., collaborate = TRUE, cloud = FALSE, locale = NULL, mathjax = NULL) {
121135

122136
if (!is.null(locale)) {
123137
p$dependencies <- c(
@@ -127,6 +141,21 @@ config <- function(p, ..., collaborate = TRUE, cloud = FALSE, locale = NULL) {
127141
p$x$config$locale <- locale
128142
}
129143

144+
if (!is.null(mathjax)) {
145+
mj <- switch(
146+
match.arg(mathjax, c("cdn", "local")),
147+
cdn = mathjax_cdn(),
148+
local = mathjax_local()
149+
)
150+
# if mathjax is already supplied overwrite it; otherwise, prepend it
151+
depNames <- sapply(p$dependencies, "[[", "name")
152+
if (any(idx <- depNames %in% "mathjax")) {
153+
p$dependencies[[which(idx)]] <- mathjax
154+
} else {
155+
p$dependencies <- c(list(mj), p$dependencies)
156+
}
157+
}
158+
130159
p$x$config <- modify_list(p$x$config, list(...))
131160

132161
nms <- sapply(p$x$config[["modeBarButtonsToAdd"]], "[[", "name")

R/mathjax.R

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#' Render TeX in a plotly graph using MathJax
2+
#'
3+
#' This function makes it slightly easier to render TeX in a plotly graph --
4+
#' it ensures that MathJax is included with the final result and also
5+
#' ensures the provided string is surrounded with `$` (this is what plotly.js
6+
#' uses to declare a string as TeX).
7+
#'
8+
#' @param x a character vector
9+
#' @export
10+
#' @seealso [config]
11+
#' @examples
12+
#'
13+
#' plot_ly(x = c(1, 2, 3, 4), y = c(1, 4, 9, 16)) %>%
14+
#' layout(title = TeX("\\text{Some mathjax: }\\alpha+\\beta x")) %>%
15+
#' config(mathjax = "cdn")
16+
17+
TeX <- function(x) {
18+
startsWithDollar <- grepl("^\\$", x)
19+
endsWithDollar <- grepl("\\$$", x)
20+
x <- paste0(if (!startsWithDollar) "$", x, if (!endsWithDollar) "$")
21+
prefix_class(x, "TeX")
22+
}
23+
24+
is.TeX <- function(x) {
25+
inherits(x, "TeX")
26+
}
27+
28+
mathjax_cdn <- function() {
29+
htmltools::htmlDependency(
30+
name = "mathjax",
31+
version = "2.7.4",
32+
src = c(file = depPath("mathjax")),
33+
script = "cdn.js"
34+
)
35+
}
36+
37+
# TODO: wait until there is a more official way to include query parameters?
38+
# https://github.com/rstudio/htmltools/issues/98
39+
mathjax_local <- function() {
40+
path <- mathjax_path()
41+
42+
mj <- file.path(path, "MathJax.js")
43+
if (!file.exists(mj)) stop("Couldn't locate MathJax.js")
44+
45+
# parse the version
46+
mathjax <- readLines(mj)
47+
pat <- 'MathJax.fileversion="[0-9].[0-9].[0-9]'
48+
ver <- regmatches(mathjax, regexpr(pat, mathjax))
49+
ver <- sub('"', '', strsplit(ver, "=")[[1]][2])
50+
51+
# make sure we have access to the right config
52+
config <- file.path(path, "config", "TeX-AMS-MML_SVG.js")
53+
if (!file.exists(config)) stop("Couldn't locate necessary MathJax config: TeX-AMS-MML_SVG")
54+
55+
htmltools::htmlDependency(
56+
name = "mathjax",
57+
version = ver,
58+
src = path,
59+
script = c("MathJax.js", "config/TeX-AMS-MML_SVG.js")
60+
)
61+
}
62+
63+
64+
mathjax_path <- function() {
65+
path <- Sys.getenv("PLOTLY_MATHJAX_PATH", NA)
66+
67+
if (!is.na(path)) {
68+
mj <- file.path(path, "MathJax.js")
69+
if (!file.exists(mj)) stop("Couldn't find 'MathJax.js' file in local directory")
70+
return(path)
71+
}
72+
73+
stop(
74+
"To use a local version of MathJax with plotly, set the PLOTLY_MATHJAX_PATH",
75+
"environment variable to the location of MathJax.",
76+
call. = FALSE
77+
)
78+
}

R/orca.R

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
#' Applies to all output images.
1212
#' @param height Sets the image height. If not set, defaults to `layout.height` value.
1313
#' Applies to all output images.
14-
#' @param mathjax whether or not to specify a path to mathjax (required to export LaTeX characters).
15-
#' This should 'just work' in RStudio, but outside RStudio, you may have to set
16-
#' the PLOTLY_MATHJAX_PATH environment variable to the location of MathJax.
14+
#' @param mathjax whether or not to include MathJax (required to render [TeX]).
15+
#' If `TRUE`, the PLOTLY_MATHJAX_PATH environment variable must be set and point
16+
#' to the location of MathJax (this variable is also used to render [TeX] in
17+
#' interactive graphs, see [config]).
1718
#' @param parallel_limit Sets the limit of parallel tasks run.
1819
#' @param verbose Turn on verbose logging on stdout.
1920
#' @param debug Starts app in debug mode and turn on verbose logs on stdout.
@@ -25,9 +26,7 @@
2526
#'
2627
#' \dontrun{
2728
#' p <- plot_ly(z = ~volcano) %>% add_surface()
28-
#' orca(p, "surface-plot.png")
2929
#' orca(p, "surface-plot.svg")
30-
#' orca(p, "surface-plot.pdf")
3130
#' }
3231
#'
3332

@@ -65,25 +64,9 @@ orca <- function(p, file = "plot.png", format = tools::file_ext(file),
6564
if (!is.null(height)) args <- c(args, "--height", height)
6665
if (!is.null(parallel_limit)) args <- c(args, "--parallel-limit", parallel_limit)
6766
if (!is.na(mapbox_token())) args <- c(args, "--mapbox-access-token", mapbox_token())
68-
if (isTRUE(mathjax)) args <- c(args, "--mathjax", mathjax_path())
67+
if (isTRUE(mathjax)) args <- c(args, "--mathjax", file.path(mathjax_path(), "MathJax.js"))
6968

7069
# TODO: point to local topojson? Should this only work if plot_geo(standalone = TRUE)?
7170
try_library("processx", "orca")
7271
invisible(processx::run("orca", args, echo = TRUE, spinner = TRUE))
7372
}
74-
75-
76-
mathjax_path <- function() {
77-
if (is_rstudio()) {
78-
try_library("rmarkdown", "orca")
79-
return(getFromNamespace("pandoc_mathjax_local_path", "rmarkdown")())
80-
}
81-
path <- Sys.getenv("PLOTLY_MATHJAX_PATH", Sys.getenv("RMARKDOWN_MATHJAX_PATH", NA))
82-
if (!is.na(path)) return(normalizePath(path, mustWork = TRUE))
83-
stop(
84-
"Please set either the RMARKDOWN_MATHJAX_PATH or PLOTLY_MATHJAX_PATH ",
85-
"environment variable to the location of MathJax. ",
86-
"On Linux systems you can also install MathJax using your system package manager.",
87-
call. = FALSE
88-
)
89-
}

R/plotly.R

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,9 @@ plot_mapbox <- function(data = data.frame(), ...) {
257257
#'
258258
#' @param data A data frame (optional).
259259
#' @param ... arguments passed along to [plot_ly()].
260+
#' @param offline whether or not to include geo assets so that the map
261+
#' can be viewed with or without an internet connection. The plotlyGeoAssets
262+
#' package is required for this functionality.
260263
#' @export
261264
#' @author Carson Sievert
262265
#' @seealso [plot_ly()], [plot_mapbox()], [ggplotly()]
@@ -267,8 +270,22 @@ plot_mapbox <- function(data = data.frame(), ...) {
267270
#' plot_geo(x = ~long, y = ~lat) %>%
268271
#' add_markers(size = I(1))
269272
#'
270-
plot_geo <- function(data = data.frame(), ...) {
273+
plot_geo <- function(data = data.frame(), ..., offline = FALSE) {
271274
p <- plot_ly(data, ...)
275+
276+
if (isTRUE(offline)) {
277+
if (system.file(package = "plotlyGeoAssets") == "") {
278+
stop(
279+
"The plotlyGeoAssets package is required to make 'offline' maps. ",
280+
"Please install and try again.",
281+
call. = FALSE
282+
)
283+
}
284+
p$dependencies <- c(
285+
list(plotlyGeoAssets::geo_assets()),
286+
p$dependencies
287+
)
288+
}
272289
# not only do we use this for is_geo(), but also setting the layout attr
273290
# https://plot.ly/r/reference/#layout-geo
274291
p$x$layout$mapType <- "geo"
@@ -429,7 +446,7 @@ typedArrayPolyfill <- function() {
429446
plotlyMainBundle <- function() {
430447
htmltools::htmlDependency(
431448
"plotly-main",
432-
version = "1.38.2",
449+
version = "1.38.3",
433450
src = depPath("plotlyjs"),
434451
script = "plotly-latest.min.js",
435452
all_files = FALSE

0 commit comments

Comments
 (0)