diff --git a/DESCRIPTION b/DESCRIPTION index 70913f6..4584e38 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,5 +1,5 @@ Package: apexcharter -Version: 0.1.4.910 +Version: 0.1.4.920 Title: Create Interactive Chart with the JavaScript 'ApexCharts' Library Description: Provides an 'htmlwidgets' interface to 'apexcharts.js'. 'Apexcharts' is a modern JavaScript charting library to build interactive charts and visualizations with simple API. diff --git a/NAMESPACE b/NAMESPACE index 5e55e01..0b5ba8c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -51,6 +51,7 @@ export(pie_opts) export(radialBar_opts) export(renderApexchart) export(run_input_demo) +export(run_sync_demo) export(set_input_click) export(set_input_selection) export(set_input_zoom) @@ -67,5 +68,6 @@ importFrom(rlang,as_label) importFrom(rlang,eval_tidy) importFrom(shiny,getDefaultReactiveDomain) importFrom(shiny,registerInputHandler) +importFrom(shiny,shinyAppFile) importFrom(stats,setNames) importFrom(utils,modifyList) diff --git a/NEWS.md b/NEWS.md index 062ac98..c6ce616 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,7 @@ apexcharter 0.1.5 ================== * Updated ApexCharts.js to 3.18.1 +* `apex()` has a new argument `synchronize` to easily synchronize charts together. ## New functions diff --git a/R/apex.R b/R/apex.R index d31ee0f..5e47765 100644 --- a/R/apex.R +++ b/R/apex.R @@ -16,6 +16,7 @@ #' @param auto_update In Shiny application, update existing chart #' rather than generating new one. Can be \code{TRUE}/\code{FALSE} or #' use \code{\link{config_update}} for more control. +#' @param synchronize Give a common id to charts to synchronize them (tooltip and zoom). #' @param serie_name Name for the serie displayed in tooltip, #' only used for single serie. #' @param width A numeric input in pixels. @@ -32,6 +33,7 @@ #' @example examples/apex.R apex <- function(data, mapping, type = "column", ..., auto_update = TRUE, + synchronize = NULL, serie_name = NULL, width = NULL, height = NULL, elementId = NULL) { type <- match.arg( @@ -58,10 +60,16 @@ apex <- function(data, mapping, type = "column", ..., ) } else { opts <- list( - chart = list(type = correct_type(type)), + chart = dropNulls(list( + type = correct_type(type), + group = synchronize + )), series = make_series(mapdata, mapping, type, serie_name) ) } + if (!is.null(synchronize)) { + opts$yaxis$labels$minWidth <- 15 + } opts <- modifyList(opts, choose_config(type, mapdata)) ax <- apexchart( ax_opts = opts, diff --git a/R/shiny-input.R b/R/shiny-input.R index 2c19bbd..74e9caf 100644 --- a/R/shiny-input.R +++ b/R/shiny-input.R @@ -174,6 +174,8 @@ set_input_selection <- function(ax, inputId, type = c("x", "xy", "y"), #' @param example Name of the example. #' #' @export +#' +#' @importFrom shiny shinyAppFile #' #' @examples #' if (interactive()) { @@ -194,6 +196,23 @@ run_input_demo <- function(example = c("click", "zoom", "selection")) { - +#' Run Shiny synchronization example +#' +#' @export +#' +#' @importFrom shiny shinyAppFile +#' +#' @examples +#' if (interactive()) { +#' +#' run_sync_demo() +#' +#' } +run_sync_demo <- function() { + shiny::shinyAppFile( + appFile = system.file("example-sync", "app.R", package = "apexcharter"), + options = list("display.mode" = "showcase") + ) +} diff --git a/inst/example-sync/app.R b/inst/example-sync/app.R new file mode 100644 index 0000000..db4b9ed --- /dev/null +++ b/inst/example-sync/app.R @@ -0,0 +1,65 @@ + +library(shiny) +library(apexcharter) +data("economics", package = "ggplot2") + + +ui <- fluidPage( + tags$h3("Synchronize tooltip, zoom and panning between several charts"), + fluidRow( + column( + width = 6, + apexchartOutput("a1"), + apexchartOutput("a3") + ), + column( + width = 6, + apexchartOutput("a2") + ) + ) +) + +server <- function(input, output, session) { + + output$a1 <- renderApexchart({ + apex( + data = tail(economics, 350), + mapping = aes(x = date, y = uempmed), + type = "line", + synchronize = "economics" + ) %>% + ax_labs( + title = "Median duration of unemployment", + y = "In weeks" + ) + }) + + output$a2 <- renderApexchart({ + apex( + data = tail(economics, 350), + mapping = aes(x = date, y = psavert), + type = "line", + synchronize = "economics" + ) %>% + ax_labs( + title = "Personal savings rate", + y = "Percentage" + ) + }) + + output$a3 <- renderApexchart({ + apex( + data = tail(economics, 350), + mapping = aes(x = date, y = pce), + type = "line", + synchronize = "economics" + ) %>% + ax_labs( + title = "Personal consumption expenditures", + y = "In billions of dollars" + ) + }) + +} + +shinyApp(ui, server) \ No newline at end of file diff --git a/inst/htmlwidgets/apexcharter.js b/inst/htmlwidgets/apexcharter.js index 6db1c72..2239707 100644 --- a/inst/htmlwidgets/apexcharter.js +++ b/inst/htmlwidgets/apexcharter.js @@ -132,6 +132,9 @@ HTMLWidgets.widget({ } axOpts.chart.width = width; axOpts.chart.height = height; + if (!axOpts.chart.hasOwnProperty("id")) { + axOpts.chart.id = el.id; + } if (!axOpts.chart.hasOwnProperty("parentHeightOffset")) { axOpts.chart.parentHeightOffset = 0; } diff --git a/man/apex.Rd b/man/apex.Rd index e767d98..3e72b00 100644 --- a/man/apex.Rd +++ b/man/apex.Rd @@ -10,6 +10,7 @@ apex( type = "column", ..., auto_update = TRUE, + synchronize = NULL, serie_name = NULL, width = NULL, height = NULL, @@ -34,6 +35,8 @@ a \code{data.frame}, it will be coerced to with \code{as.data.frame}.} rather than generating new one. Can be \code{TRUE}/\code{FALSE} or use \code{\link{config_update}} for more control.} +\item{synchronize}{Give a common id to charts to synchronize them (tooltip and zoom).} + \item{serie_name}{Name for the serie displayed in tooltip, only used for single serie.} diff --git a/man/run_sync_demo.Rd b/man/run_sync_demo.Rd new file mode 100644 index 0000000..10e6eb6 --- /dev/null +++ b/man/run_sync_demo.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/shiny-input.R +\name{run_sync_demo} +\alias{run_sync_demo} +\title{Run Shiny synchronization example} +\usage{ +run_sync_demo() +} +\description{ +Run Shiny synchronization example +} +\examples{ +if (interactive()) { + + run_sync_demo() + +} +} diff --git a/vignettes/sync-charts.Rmd b/vignettes/sync-charts.Rmd index 9b1f7eb..ede3d05 100644 --- a/vignettes/sync-charts.Rmd +++ b/vignettes/sync-charts.Rmd @@ -22,26 +22,22 @@ data("economics", package = "ggplot2") ## Sync charts -With [Apexcharts](https://apexcharts.com) you can sync (tooltip, zoom) several charts together by providing a group and id to each charts. This works in Shiny and Markdown. Here an example where we create two charts, tooltip will be displayed on both charts when you hover one, and if you zoom on one, the other one will be synced : +With [Apexcharts](https://apexcharts.com) you can sync (tooltip, zoom) several charts together by providing a common id in `synchronize` argument. This works in Shiny and Markdown. Here an example where we create two charts, tooltip will be displayed on both charts when you hover one, and if you zoom on one, the other one will be synced : ```{r example-1, eval=FALSE} apex( data = tail(economics, 150), mapping = aes(x = date, y = pce), - type = "line" -) %>% - ax_chart( - group = "economics", id = "pce" # <- define common group and unique id - ) + type = "line", + synchronize = "economics" +) apex( data = tail(economics, 150), mapping = aes(x = date, y = psavert), - type = "line" -) %>% - ax_chart( - group = "economics", id = "psavert" # <- define common group and unique id - ) + type = "line", + synchronize = "economics" +) ``` @@ -50,6 +46,14 @@ apex( ``` +For an example in Shiny, you can run: + +```{r shiny-example, eval=FALSE} +run_sync_demo() +``` + + + ## Brush chart