Changes in version 4.12.0.9000 - Completed the plot_ly() documentation for what happens when type is not specified (#2362). - Removed the dependency on the {lazyeval} package. Bug fixes - Closed #2483: save_image() no longer embeds Windows file paths directly into Python source passed to reticulate, fixing static image export with Kaleido on Windows. Changes in version 4.12.0 (2026-01-24) Changes to plotly.js Upgrades plotly.js from v2.11.1 to v2.25.2 (35 releases). Key new features now available: - Multiple legends: Support for legend2, legend3, etc. with separate positioning and visibility control - Shape labels: New label attribute for shapes and label.texttemplate for parametric shapes - Marker direction: New marker.angle, marker.angleref, and marker.standoff properties for directional markers - Y-axis positioning: shift and autoshift properties to avoid y-axis overlapping in multi-axis plots - Mapbox clustering: Clustering options and bounds support for scattermapbox traces - Equal Earth projection: New map projection option for geo subplots - Pattern fills: Pattern support extended to pie, funnelarea, sunburst, icicle, and treemap charts - Editable selections: Persistent and editable selections over cartesian subplots with editSelection config option - Axis label aliases: labelalias for simplified axis label customization - Grid styling: griddash property and minor tick/grid line styling options Also includes a security fix for prototype pollution and ~90KB bundle size reduction. See the plotly.js releases page for the full changelog. Improvements - save_image() now works with kaleido v1.0 and higher. (#2447) Bug fixes - plotly_build() now works with ggmatrix objects (e.g., from GGally::ggpairs()). (#2447) - Closed #2415: ggplotly() now shows variables named 'group' in tooltips when mapped to aesthetics like colour. - Closed #2455, #2460: ggplotly() no longer creates empty shapes when panel.border is element_blank() (ggplot2 4.0.0 compatibility). - Closed #2466: ggplotly() no longer errors when scale_*_manual() has unused aesthetics (e.g., aesthetics = c("colour", "fill") when only colour is used). - Closed #2305: ggplotly() now respects geom_boxplot(outlier.shape = NA) to hide outlier points. - Closed #2467: ggplotly() now correctly shows legends and splits traces when scales have multiple aesthetics. - Closed #2407, #2187: ggplotly() now translates legend.position theme element to plotly layout (supports "bottom", "top", "left", and numeric positions). - Closed #2281: ggplotly() no longer drops legends when geom_blank() is present in the plot. Changes in version 4.11.0 (2025-06-19) New features - ggplotly() now supports the {ggridges} package. (#2314) Improvements - Various updates to ggplotly() to better support recent versions of ggplot2. (#2315, #2368, #2442, thanks @teunbrand). Bug fixes - Closed #2337: Creating a new event_data() handler no longer causes a spurious reactive update of existing event_data()s. (#2339) - Closed #2376: Removes errant boxmode warning for grouped boxplot. (#2396) - Closed #2392: Trivial warning about RColorBrewer minimal n value is no longer thrown (#1999) Changes in version 4.10.4 (2024-01-13) Improvements - ggplotly() now works better with the development version of ggplot2 (> v3.4.4). (#2315) Changes in version 4.10.3 (2023-10-21) Improvements - ggplotly() now works better with the development version of ggplot2 (> v3.4.3). (#2301) Bug fixes - Closed #1947: ggplotly() now correctly handles geom_vline/geom_hline with empty data. Previously, if geom_vline/geom_hline was passed an empty data frame, it would result in an error. The plot is drawn even if no lines are found; this is the same behavior as ggplot2. - Closed #1214: Do not warn in RStudio on Windows when scattergl is used. Recent RStudio versions can render scattergl correctly. - Closed #2298: Fix fill assignment in geom_point when a single shape value was used with multiple fill and colour values mapped (@zeehio) Changes in version 4.10.2 (2023-06-03) New features - Closed #2216: Additional selectize.js options can now be passed along to highlight()'s selectize argument. (#2217) Improvements - Closed #2259: ggplotly() now provides better support for ggplot2 >v3.4.2. (#2262) Bug fixes - Closed #2212: ggplotly() no longer silently drops legends that are customized through ggplot2::guide_legend(). - Closed #2179: save_image() no longer needs reticulate::py_run_string("import sys") in order to run without error. (#2179) - Closed #2218: highlight(selectize = TRUE) no longer yields an incorrect selectize.js result when there is a combination of crosstalk and non-crosstalk traces. (#2217) - Closed #2208: ggplotly() no longer errors given a geom_area() with 1 or less data points (error introduced by new behavior in ggplot2 v3.4.0). (#2209) - Closed #2220: ggplotly() no longer errors on stat_summary(geom = "crossbar"). (#2222) - Closed #2212: ggplotly() no longer removes legends when setting guide properties via guides(aes = guide_xxx(...)). Changes in version 4.10.1 (2022-11-07) Changes to plotly.js - This version of the R package upgrades the version of the underlying plotly.js library from v2.5.1 to v2.11.1. This includes many bug fixes and improvements. The plotly.js release page has the full list of changes. New features - plotlyOutput() gains a new fill parameter. When TRUE (the default), the widget's container element is allowed to grow/shrink to fit it's parent container so long as that parent is opinionated about its height and has been marked with htmltools::bindFillRole(x, container = TRUE). (#2198) - The primary motivation for this is to allow plots to grow/shrink by default inside bslib::card_body_fill() - ggplotly() now supports the {ggalluvial} package. (#2061, thanks @moutikabdessabour) - highlight() now supports on="plotly_selecting", enabling client-side linked brushing via mouse click+drag (no mouse-up event required, as with on="plotly_selected"). (#1280) - raster2uri() supports nativeRaster objects. This enables nativeRaster support for the annotation_raster() geom (#2174, @zeehio). Bug fixes - ggplotly() now converts stat_ecdf() properly. (#2065) - ggplotly() now correctly handles geom_tile() with no fill aesthetic. (#2063) - ggplotly() now respects guide(aes = "none") (e.g., guide(fill = "none")) when constructing legend entries. (#2067) - Fixed an issue with translating GGally::ggcorr() via ggplotly(). (#2012) - Fixed an issue where clearing a crosstalk filter would raise an error in the JS console (#2087) - Fixed an issue where map_color() would throw an error on R 4.2 (#2131) Improvements - ggplotly() does not issue warnings with options(warnPartialMatchArgs = TRUE) any longer. (#2046, thanks @bersbersbers) - ggplotly() does not issue warnings related to use of deprecated tidyr::gather_() in internals. (#2125, thanks @simonpcouch) Changes in version 4.10.0 (2021-10-09) Breaking changes in JavaScript API - This version of the R package upgrades the version of the underlying plotly.js library from v1.57.1 to v2.5.1. This includes many breaking changes, bug fixes, and improvements to the underlying JavaScript library. Most of the breaking changes are summarized in this announcement of the 2.0 release, but see here for the full changelog. Breaking changes in R API - ggplotly() now uses the layout.legend.title (instead of layout.annotations) plotly.js API to convert guides for discrete scales. (#1961) - renderPlotly() now uses Plotly.react() (instead of Plotly.newPlot()) to redraw when layout(transition = ) is specified. This makes it possible/easier to implement a smooth transitions when renderPlotly() gets re-executed. (#2001) New Features - Added new functions for static image exporting via the kaleido python package, namely save_image() and kaleido(). See help(save_image, package = "plotly") for installation info and example usage. (#1971) Improvements - ggplotly() now better positions axis titles for facet_wrap()/facet_grid(). (#1975) Changes in version 4.9.4.1 (2021-06-18) BUG FIXES - Fixes a bug in ggplotly() with {crosstalk} and {ggplot2} v3.3.4 (#1952). Changes in version 4.9.4 (2021-06-08) BUG FIXES - Duplicate highlight(selectize=T) dropdowns are no longer rendered in Shiny (#1936). - group_by.plotly() now properly retains crosstalk information across {dplyr} versions (#1920). - Adds fixes in ggplotly() for the upcoming {ggplot2} v3.3.4 release (#1952). - Fixes some issues with name and frames when both attributes are specified. (#1903 and #1618). Changes in version 4.9.3 (2021-01-10) Changes to plotly.js - This version of the R package upgrades the version of the underlying plotly.js library from v1.52.2 to v1.57.1. This includes many bug fixes and improvements. The plotly.js release page has the full list of changes. NEW FEATURES - renderPlotly() now works well with shiny::bindCache(), meaning that plotly graphs can now be persistently cached in Shiny apps with renderPlotly(expr) %>% shiny::bindCache() (#1879). - ggplotly() now works well with the thematic package. That is, it can now correctly translate ggplot2 styling that derives from thematic. Note that, in order to use thematic's auto theming in Shiny with ggplotly(), you need shiny v1.5.0 (or higher) and htmlwidgets v1.5.2.9000 (or higher). Relatedly, if these versions are available, one may now also call getCurrentOutputInfo() inside renderPlotly() to get CSS styles of the output container (#1801 and #1802). IMPROVEMENTS - All HTTP requests are now retried upon failure (#1656, @jameslamb). - R linebreaks (\n) in factor labels are now translated to HTML linebreaks (
), too. Before, this conversion was only done for colums of type character. (#1700, @salim-b). BUG FIXES - When R's POSIXt class is serialized to JSON, the time of day is now correctly preserved (in plotly.js expected 'yyyy-mm-dd HH:MM:SS.ssssss' format). This should fix a whole host of issues where date-times were being rounded. (#1871, @FlukeAndFeather). - ggplotly() now handles discrete axes of a facet_wrap and facet_grid correctly when there is only one category in panels > 1 (#1577 and #1720). - ggplotly() now correctly accounts for linebreaks in tick label text when computing plot margins (#1791, @trekonom). - ggplotly() now handles element_blank() and factor() labels in positional scales correctly (#1731 and #1772). - ggplotly() now handles missing y aesthetic in geom_errorbar() (#1779, @trekonom). Changes in version 4.9.2.1 (2020-04-04) This is minor patch release with a few minor bug fixes and updates test expectations in anticipation of new R 4.0 defaults. BUG FIXES - Fixes rendering issues non-HTML rmarkdown output formats, which was introduced in the 4.9.2 release (#1702). - Fixes a ggplotly() bug in axis tick translation (#1725, #1721). - plot_mapbox() now correctly defaults to a scattermapbox trace (unless z is present, then it defaults to choroplethmapbox) (#1707). - ggplotly() now correctly resolves overlapping axis tick text in coord_sf() (#1673). - A false-positive warning is no longer thrown when attempting to cast toWebGL() (#1569). Changes in version 4.9.2 (2020-02-12) Changes to plotly.js - This version of the R package upgrades the version of the underlying plotly.js library from v1.49.4 to v1.52.2. This includes many bug fixes, improvements, as well as 2 new trace types: treemap and image. The plotly.js release page has the full list of changes. IMPROVEMENTS - The add_image() function was added to make it easier to create image traces via raster objects. BUG FIXES - add_sf()/geom_sf() now correctly handle geometry columns that are named something other than "geometry" (#1659). - Specifying an english locale no longer results in error (#1686). Changes in version 4.9.1 (2019-11-07) Changes to plotly.js - This version of the R package upgrades the version of the underlying plotly.js library from v1.46.1 to v1.49.4. The plotly.js release page has the full list of changes. IMPROVEMENTS - event_data() gains support for the plotly_sunburstclick event (#1648) BUG FIXES - Fixed an issue with correctly capturing the return value of user-expressions to renderPlotly() (#1528). - Fixed a resizing issue where graphs could be incorrectly resized to their initial size in some cases (#1553). - ggplotly() now positions the x-axis in the last column of a facet_wrap() properly (#1501). - ggplotly() now handles geom_hline()/geom_vline() correctly in conjunction with coord_flip() (#1519). - event_data() now correctly relays the key attribute for statistical traces (#1610). Changes in version 4.9.0 (2019-04-10) Changes to plotly.js - This version of the R package upgrades the version of the underlying plotly.js library from v1.42.3 to v1.46.1. The plotly.js release page has the full list of changes, but here is summary most pertainent ones for the R package: - New trace types: sunburst, waterfall, isosurface. - New hovertemplate attribute allows for finer-tuned control over tooltip text. See here for an example. - Providing a string to title is now deprecated (but still works). Instead, use title = list(text = "title"). This change was made to support a new title placement API (e.g., title = list(text = "title", xanchor = "left")). Note that these changes are relevant for layout.title as well as layout.xaxis.title/layout.yaxis.title/etc. NEW FEATURES & IMPROVEMENTS - Several new features and improvements related to accessing plotly.js events in shiny (learn more about them in this RStudio webinar): - The event argument of the event_data() function now supports the following events: plotly_selecting, plotly_brushed, plotly_brushing, plotly_restyle, plotly_legendclick, plotly_legenddoubleclick, plotly_clickannotation, plotly_afterplot, plotly_doubleclick, plotly_deselect, plotly_unhover. For examples, see plotly_example("shiny", "event_data"), plotly_example("shiny", "event_data_legends"), and plotly_example("shiny", "event_data_annotation"), - New event_register() and event_unregister() functions for declaring which events to transmit over the wire (i.e., from the browser to the shiny server). Events that are likely to have large overhead are not registered by default, so you'll need to register these: plotly_selecting, plotly_unhover, plotly_restyle, plotly_legendclick, and plotly_legenddoubleclick. - A new priority argument. By setting priority='event', the event is treated like a true event: any reactive expression using the event becomes invalidated (regardless of whether the input values has changed). For an example, see plotly_example("shiny", "event_priority"). - The event_data() function now relays the (official plotly.js) customdata attribute in similar fashion to (unofficial) key attribute (#1423). Run plotly_example("shiny", "event_data") for an example. - event_data("plotly_selected") is no longer too eager to clear. That is, it is no longer set to NULL when clicking on a plot after triggering the "plotly_selected" event (#1121) (#1122). - Several new features and improvements for exporting static graphs with the orca command-line utility: - The orca() function now supports conversion of much larger figures (#1322) and works without a mapbox api token (#1314). - The orca_serve() function was added for efficient exporting of many plotly graphs. For examples, see help(orca_serve). - The orca() function gains new arguments more_args and ... for finer control over the underlying system commands. - ggplotly() now respects horizontal alignment of ggplot2 titles (e.g., ggplotly(qplot(1:10) + ggtitle("A title") + theme(plot.title = element_text(hjust = 1)))). - plotly objects can now be serialized and unserialized in different environments (i.e., you can now use saveRDS() to save an object as an rds file and restore it on another machine with readRDS()). Note this object is dynamically linked to JavaScript libraries, so one should take care to use consistent versions of plotly when serializing and unserializing (#1376). - The style() function now supports "partial updates" (i.e. modification of a particular property of an object, rather than the entire object). For example, notice how the first plot retains the original marker shape (a square): p <- plot_ly(x = 1:10, y = 1:10, symbol = I(15)); subplot(style(p, marker.color = "red"), style(p, marker = list(color = "red"))) (#1342). - The method argument of plotlyProxyInvoke() gains support for a "reconfig" method. This makes it possible to modify just the configuration of a plot in a shiny app. For an example use, see plotly_example("shiny", "event_data_annotation"). - The plotly_example() function will now attempt to open the source file(s) used to run the example. Set edit = FALSE to prevent the source file(s) from opening. - An informative warning is now thrown if invalid argument names are supplied to config(). CHANGES - If stroke is specified, span now defaults to I(1). This results in a slightly narrower default span for some trace types (e.g., box, contour), but it also ensures the stroke is always visible when it's relevant (e.g. plot_ly(x = 1:10, y = 1:10, stroke = I("black"))), making for a more consistent overall default (#1507). - The 'collaborate' button no longer appears in the modebar, and is longer supported, so the config() function no longer has a collaborate argument. - The cloud argument is now deprecated and will be removed in a future version. Use showSendToCloud instead. - ggplotly() now translates title information to layout.title.text (instead of layout.title) and layout.title.font (instead of layout.titlefont) BUG FIXES - subplot() now works much better with annotations, images, and shapes: - When xref/yref references an x/y axis these references are bumped accordingly (#1181). - When xref/yref references paper coordinates, these coordinates are updated accordingly (#1332). - subplot() now repositions shapes with fixed height/width (i.e., xsizemode/ysizemode of "pixel") correctly (#1494). - The colorscale attribute now correctly handles a wider range of input values (#1432, #1485) - The colorscale generated via the color argument in plot_ly() now uses an evenly spaced grid of values instead of quantiles (#1308). - When using shinytest to test a shiny that contains plotly graph, false positive differences are no longer reported (rstudio/shinytest#174). - When the size argument maps to marker.size, it now converts to an array of appropriate length (#1479). - The color and stroke arguments now work as expected for trace types with fillcolor but no fill attribute (e.g. box traces) (#1292). - Information emitted by in event_data() for heatmaps with atomic vectors for x/y/z is now correct (#1141). - Fixed issue where dplyr groups caused a problem in the ordering of data arrays passed to marker objects (#1351). - In some cases, a ggplotly() colorbar would cause issues with hover behavior, which is now fixed (#1381). - An articial marker no longer appears when clearing a crosstalk selection of a plot with a colorbar (#1406). - Clearing a highlight event via crosstalk no longer deletes all the traces added since initial draw (#1436). - Recursive attribute validation is now only performed on recursive objects (#1315). - The text attribute is no longer collapsed to a string when hoveron='fills+points' (#1448). - layout.[x-y]axis.domain is no longer supplied a default when layout.grid is specified (#1427). - When uploading charts to a plot.ly account via api_create(), layout attributes are no longer incorrectly src-ified, which was causing inconsistencies in local/remote rendering of ggplotly() charts (#1197). Changes in version 4.8.0 (2018-07-20) NEW FEATURES & IMPROVEMENTS plotly.js and plot_ly() specific improvements - Upgraded to plotly.js v1.39.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 for a complete list of plotly.js-specific improvements. - 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 for an overview. - 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")). ggplotly() specific improvements - ggplotly() now supports conversion of ggplot2's geom_sf(). - One may now inform ggplotly() about the relevant shiny output size via session$clientData. This ensures ggplotly() sizing is closer to ggplot2 sizing, even on window resize. For an example, run plotly_example("shiny", "ggplotly_sizing"). Other improvements relevant for all plotly objects - 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