diff --git a/NAMESPACE b/NAMESPACE index 70f8943..7097128 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -45,6 +45,7 @@ export(radialBar_opts) export(renderApexchart) export(run_input_demo) export(set_input_click) +export(set_input_selection) export(set_input_zoom) importFrom(ggplot2,aes) importFrom(htmlwidgets,JS) diff --git a/R/shiny-input.R b/R/shiny-input.R index 91ae334..2c19bbd 100644 --- a/R/shiny-input.R +++ b/R/shiny-input.R @@ -15,6 +15,7 @@ #' @param effect_value A larger value intensifies the select effect, accept value between 0 and 1. #' @param session The Shiny session. #' +#' @note If x-axis is of type datetime, value retrieved is of class \code{POSIXct}. #' #' @return An \code{apexcharts} \code{htmlwidget} object. #' @export @@ -22,6 +23,19 @@ #' @importFrom shiny getDefaultReactiveDomain #' #' @examples +#' +#' library(apexcharter) +#' +#' # Not in Shiny but you can still click on bars +#' data.frame( +#' month = month.abb, +#' value = sample(1:100, 12) +#' ) %>% +#' apex(aes(month, value)) %>% +#' set_input_click("month_click", multiple = TRUE) +#' +#' +#' # Interactive examples: #' if (interactive()) { #' #' run_input_demo("click") @@ -54,8 +68,10 @@ set_input_click <- function(ax, inputId, multiple = FALSE, #' Retrieve zoom information in Shiny #' #' @param ax An \code{apexcharts} \code{htmlwidget} object. -#' @param inputId The id that will be used server-side for retrieving click. +#' @param inputId The id that will be used server-side for retrieving zoom. #' @param session The Shiny session. +#' +#' @note If x-axis is of type datetime, value retrieved is of class \code{POSIXct}. #' #' @return An \code{apexcharts} \code{htmlwidget} object. #' @export @@ -79,24 +95,95 @@ set_input_zoom <- function(ax, inputId, } - +#' Retrieve selection information in Shiny +#' +#' @param ax An \code{apexcharts} \code{htmlwidget} object. +#' @param inputId The id that will be used server-side for retrieving selection. +#' @param type Allow selection either on x-axis, y-axis or on both axis. +#' @param fill_color Background color of the selection rect which is drawn when user drags on the chart. +#' @param fill_opacity Opacity of background color of the selection rectangle. +#' @param stroke_width Border thickness of the selection rectangle. +#' @param stroke_dasharray Creates dashes in borders of selection rectangle. +#' Higher number creates more space between dashes in the border. +#' @param stroke_color Colors of selection border. +#' @param stroke_opacity Opacity of selection border. +#' @param xmin,xmax Start value of x-axis. Both \code{min} and \code{max} must be provided. +#' @param ymin,ymax Start value of y-axis. Both \code{min} and \code{max} must be provided. +#' @param session The Shiny session. +#' +#' @return An \code{apexcharts} \code{htmlwidget} object. +#' @export +#' +#' @examples +#' +#' library(apexcharter) +#' data("economics", package = "ggplot2") +#' +#' # Not in Shiny so no events +#' # but you can still select an area on chart +#' apex(economics, aes(date, psavert), type = "line") %>% +#' set_input_selection("selection") +#' +#' # Default selection at start +#' apex(economics, aes(date, psavert), type = "line") %>% +#' set_input_selection( +#' inputId = "selection", +#' xmin = format_date("1980-01-01"), +#' xmax = format_date("1985-01-01") +#' ) +set_input_selection <- function(ax, inputId, type = c("x", "xy", "y"), + fill_color = "#24292e", fill_opacity = 0.1, + stroke_width = 1, stroke_dasharray = 3, + stroke_color = "#24292e", stroke_opacity = 0.4, + xmin = NULL, xmax = NULL, ymin = NULL, ymax = NULL, + session = shiny::getDefaultReactiveDomain()) { + type <- match.arg(type) + if (is.null(session)) + session <- list(ns = identity) + selection <- list( + enabled = TRUE, type = type, + fill = list(color = fill_color, opacity = fill_opacity), + stroke = list( + width = stroke_width, dashArray = stroke_dasharray, + color = stroke_color, opacity = stroke_opacity + ) + ) + if (!is.null(xmin) & !is.null(xmax)) { + selection$xaxis <- list(min = xmin, max = xmax) + } + if (!is.null(ymin) & !is.null(ymax)) { + selection$yaxis <- list(min = ymin, max = ymax) + } + ax <- ax_chart( + ax = ax, + selection = selection, + toolbar = list(autoSelected = "selection") + ) + ax$x$shinyEvents$selection <- list( + inputId = session$ns(inputId), + type = type + ) + ax +} #' Run Shiny input events examples #' -#' @param example NAme of the example. +#' @param example Name of the example. #' #' @export #' #' @examples #' if (interactive()) { #' -#' run_input_demo() +#' run_input_demo("click") +#' run_input_demo("zoom") +#' run_input_demo("selection") #' #' } -run_input_demo <- function(example = c("click", "zoom")) { +run_input_demo <- function(example = c("click", "zoom", "selection")) { example <- match.arg(example) shiny::shinyAppFile( appFile = system.file("examples-input", example, "app.R", package = "apexcharter"), diff --git a/inst/examples-input/selection/app.R b/inst/examples-input/selection/app.R new file mode 100644 index 0000000..a42ff5d --- /dev/null +++ b/inst/examples-input/selection/app.R @@ -0,0 +1,53 @@ + +library(shiny) +library(apexcharter) +data("economics", package = "ggplot2") + +ui <- fluidPage( + tags$h2("Retrieve selection information"), + fluidRow( + column( + width = 8, + tags$b("Datetime"), + apexchartOutput("chart1") + ), + column( + width = 4, + verbatimTextOutput("result1") + ) + ), + fluidRow( + column( + width = 8, + tags$b("Scatter"), + apexchartOutput("chart2") + ), + column( + width = 4, + verbatimTextOutput("result2") + ) + ) +) + +server <- function(input, output, session) { + + output$chart1 <- renderApexchart({ + apex(economics, aes(date, psavert), type = "line") %>% + set_input_selection("selection_ts") + }) + output$result1 <- renderPrint({ + input$selection_ts + }) + + output$chart2 <- renderApexchart({ + apex(iris, aes(Sepal.Length, Sepal.Width), type = "scatter") %>% + ax_chart(zoom = list(type = "xy")) %>% + set_input_selection("selection_scatter", type = "xy") + }) + output$result2 <- renderPrint({ + input$selection_scatter + }) + +} + +shinyApp(ui, server) diff --git a/inst/examples-input/zoom/app.R b/inst/examples-input/zoom/app.R index e7c54a7..2d5f9e5 100644 --- a/inst/examples-input/zoom/app.R +++ b/inst/examples-input/zoom/app.R @@ -7,23 +7,23 @@ ui <- fluidPage( tags$h2("Retrieve zoom information"), fluidRow( column( - width = 6, + width = 8, tags$b("Datetime"), apexchartOutput("chart1") ), column( - width = 6, + width = 4, verbatimTextOutput("result1") ) ), fluidRow( column( - width = 6, + width = 8, tags$b("Scatter"), apexchartOutput("chart2") ), column( - width = 6, + width = 4, verbatimTextOutput("result2") ) ) diff --git a/inst/htmlwidgets/apexcharter.js b/inst/htmlwidgets/apexcharter.js index 5f7ab33..96f3e42 100644 --- a/inst/htmlwidgets/apexcharter.js +++ b/inst/htmlwidgets/apexcharter.js @@ -80,6 +80,24 @@ HTMLWidgets.widget({ }); }; } + if (x.shinyEvents.hasOwnProperty("selection")) { + ax_opts.chart.events.selection = function(chartContext, xaxis, yaxis) { + console.log(xaxis); + var id = x.shinyEvents.selection.inputId; + if (is_datetime(chartContext)) { + id = id + ":apex_datetime"; + } + var selectionValue; + if (x.shinyEvents.selection.type == "x") { + selectionValue = {x: xaxis.xaxis}; + } else if (x.shinyEvents.selection.type == "xy") { + selectionValue = {x: xaxis.xaxis, y: xaxis.yaxis}; + } else if (x.shinyEvents.selection.type == "y") { + selectionValue = {y: xaxis.yaxis}; + } + Shiny.setInputValue(id, selectionValue); + }; + } } // Generate or update chart @@ -200,7 +218,7 @@ function getSelection(chartContext, selectedDataPoints, serieIndex) { function getYaxis(axis) { var yzoom = { min: null, max: null }; - if (typeof axis.yaxis != "undefined") { + if (typeof axis.yaxis != "undefined" && axis.yaxis !== null && axis.yaxis.length > 0) { var y_axis = axis.yaxis[0]; if (y_axis.hasOwnProperty("min") && typeof y_axis.min != "undefined") { yzoom.min = y_axis.min; diff --git a/man/run_input_demo.Rd b/man/run_input_demo.Rd index c08383f..a819ff2 100644 --- a/man/run_input_demo.Rd +++ b/man/run_input_demo.Rd @@ -4,10 +4,10 @@ \alias{run_input_demo} \title{Run Shiny input events examples} \usage{ -run_input_demo(example = c("click", "zoom")) +run_input_demo(example = c("click", "zoom", "selection")) } \arguments{ -\item{example}{NAme of the example.} +\item{example}{Name of the example.} } \description{ Run Shiny input events examples @@ -15,7 +15,9 @@ Run Shiny input events examples \examples{ if (interactive()) { - run_input_demo() + run_input_demo("click") + run_input_demo("zoom") + run_input_demo("selection") } } diff --git a/man/set_input_click.Rd b/man/set_input_click.Rd index bb69a96..9f1b059 100644 --- a/man/set_input_click.Rd +++ b/man/set_input_click.Rd @@ -39,7 +39,23 @@ with size > 0 and set tooltip's options \code{intersect = TRUE} and \code{shared \item \strong{scatter:} retrieve XY coordinates. } } +\note{ +If x-axis is of type datetime, value retrieved is of class \code{POSIXct}. +} \examples{ + +library(apexcharter) + +# Not in Shiny but you can still click on bars +data.frame( + month = month.abb, + value = sample(1:100, 12) +) \%>\% + apex(aes(month, value)) \%>\% + set_input_click("month_click", multiple = TRUE) + + +# Interactive examples: if (interactive()) { run_input_demo("click") diff --git a/man/set_input_selection.Rd b/man/set_input_selection.Rd new file mode 100644 index 0000000..29bd0eb --- /dev/null +++ b/man/set_input_selection.Rd @@ -0,0 +1,73 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/shiny-input.R +\name{set_input_selection} +\alias{set_input_selection} +\title{Retrieve selection information in Shiny} +\usage{ +set_input_selection( + ax, + inputId, + type = c("x", "xy", "y"), + fill_color = "#24292e", + fill_opacity = 0.1, + stroke_width = 1, + stroke_dasharray = 3, + stroke_color = "#24292e", + stroke_opacity = 0.4, + xmin = NULL, + xmax = NULL, + ymin = NULL, + ymax = NULL, + session = shiny::getDefaultReactiveDomain() +) +} +\arguments{ +\item{ax}{An \code{apexcharts} \code{htmlwidget} object.} + +\item{inputId}{The id that will be used server-side for retrieving selection.} + +\item{type}{Allow selection either on x-axis, y-axis or on both axis.} + +\item{fill_color}{Background color of the selection rect which is drawn when user drags on the chart.} + +\item{fill_opacity}{Opacity of background color of the selection rectangle.} + +\item{stroke_width}{Border thickness of the selection rectangle.} + +\item{stroke_dasharray}{Creates dashes in borders of selection rectangle. +Higher number creates more space between dashes in the border.} + +\item{stroke_color}{Colors of selection border.} + +\item{stroke_opacity}{Opacity of selection border.} + +\item{xmin, xmax}{Start value of x-axis. Both \code{min} and \code{max} must be provided.} + +\item{ymin, ymax}{Start value of y-axis. Both \code{min} and \code{max} must be provided.} + +\item{session}{The Shiny session.} +} +\value{ +An \code{apexcharts} \code{htmlwidget} object. +} +\description{ +Retrieve selection information in Shiny +} +\examples{ + +library(apexcharter) +data("economics", package = "ggplot2") + +# Not in Shiny so no events +# but you can still select an area on chart +apex(economics, aes(date, psavert), type = "line") \%>\% + set_input_selection("selection") + +# Default selection at start +apex(economics, aes(date, psavert), type = "line") \%>\% + set_input_selection( + inputId = "selection", + xmin = format_date("1980-01-01"), + xmax = format_date("1985-01-01") + ) +} diff --git a/man/set_input_zoom.Rd b/man/set_input_zoom.Rd index 3ce361d..712d231 100644 --- a/man/set_input_zoom.Rd +++ b/man/set_input_zoom.Rd @@ -9,7 +9,7 @@ set_input_zoom(ax, inputId, session = shiny::getDefaultReactiveDomain()) \arguments{ \item{ax}{An \code{apexcharts} \code{htmlwidget} object.} -\item{inputId}{The id that will be used server-side for retrieving click.} +\item{inputId}{The id that will be used server-side for retrieving zoom.} \item{session}{The Shiny session.} } @@ -19,6 +19,9 @@ An \code{apexcharts} \code{htmlwidget} object. \description{ Retrieve zoom information in Shiny } +\note{ +If x-axis is of type datetime, value retrieved is of class \code{POSIXct}. +} \examples{ if (interactive()) {