From c65591a727d430f38ad176c104888628010b5bfb Mon Sep 17 00:00:00 2001 From: pvictor Date: Sun, 9 Sep 2018 22:09:05 +0200 Subject: [PATCH] proxy method v1 --- NAMESPACE | 2 + R/proxy.R | 95 +++++++++++++++++++++++++ inst/examples/heatmap.R | 40 ++++++++--- inst/examples/proxy-update-serie-line.R | 47 ++++++++++++ inst/htmlwidgets/apexcharter.js | 6 +- man/apexchartProxy.Rd | 19 +++++ man/ax_proxy_series.Rd | 29 ++++++++ 7 files changed, 227 insertions(+), 11 deletions(-) create mode 100644 R/proxy.R create mode 100644 inst/examples/proxy-update-serie-line.R create mode 100644 man/apexchartProxy.Rd create mode 100644 man/ax_proxy_series.Rd diff --git a/NAMESPACE b/NAMESPACE index 6dc6654..a5cb4d3 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -3,6 +3,7 @@ export("%>%") export(apexchart) export(apexchartOutput) +export(apexchartProxy) export(ax_annotations) export(ax_chart) export(ax_colors) @@ -13,6 +14,7 @@ export(ax_labels) export(ax_legend) export(ax_markers) export(ax_plotOptions) +export(ax_proxy_series) export(ax_responsive) export(ax_series) export(ax_series2) diff --git a/R/proxy.R b/R/proxy.R new file mode 100644 index 0000000..5ddd351 --- /dev/null +++ b/R/proxy.R @@ -0,0 +1,95 @@ + +#' @title Proxy for \code{apexchart} +#' +#' @description Allow to update a chart in Shiny application. +#' +#' @param shinyId single-element character vector indicating the output ID of the +#' chart to modify (if invoked from a Shiny module, the namespace will be added +#' automatically) +#' @param session the Shiny session object to which the chart belongs; usually the +#' default value will suffice +#' +#' @export +#' +apexchartProxy <- function(shinyId, session = shiny::getDefaultReactiveDomain()) { + + if (is.null(session)) { + stop("apexchartProxy must be called from the server function of a Shiny app") + } + + if (!is.null(session$ns) && nzchar(session$ns(NULL)) && substring(shinyId, 1, nchar(session$ns(""))) != session$ns("")) { + shinyId <- session$ns(shinyId) + } + + structure( + list( + session = session, + id = shinyId, + x = list() + ), + class = "apexchart_Proxy" + ) +} + + +#' Call a proxy method +#' +#' @param proxy A \code{apexchartProxy} \code{htmlwidget} object. +#' @param name Proxy method. +#' @param ... Arguments passed to method. +#' +#' @return A \code{apexchartProxy} \code{htmlwidget} object. +#' @noRd +.ax_proxy <- function(proxy, name, ...) { + if (!"apexchart_Proxy" %in% class(proxy)) + stop("This function must be used with a apexchartProxy object", call. = FALSE) + proxy$session$sendCustomMessage( + type = sprintf("update-apexchart-%s", name), + message = list(id = proxy$id, data = list(...)) + ) + proxy +} +.ax_proxy2 <- function(proxy, name, l) { + if (!"apexchart_Proxy" %in% class(proxy)) + stop("This function must be used with a apexchartProxy object", call. = FALSE) + proxy$session$sendCustomMessage( + type = sprintf("update-apexchart-%s", name), + message = list(id = proxy$id, data = l) + ) + proxy +} + + + + +#' @title Proxy for updating series. +#' +#' @description Allows you to update the series array overriding the existing one. +#' +#' @param proxy A \code{apexchartProxy} \code{htmlwidget} object. +#' @param newSeries The series array to override the existing one. +#' @param animate Should the chart animate on re-rendering. +#' +#' @export +#' +#' @examples +#' \dontrun{ +#' +#' if (interactive()) { +#' +#' +#' +#' } +#' +#' } +ax_proxy_series <- function(proxy, newSeries, animate = TRUE) { + .ax_proxy2( + proxy = proxy, + name = "series", + l = list(newSeries = list(newSeries), animate = animate) + ) +} + + + + diff --git a/inst/examples/heatmap.R b/inst/examples/heatmap.R index 447619e..95e74ae 100644 --- a/inst/examples/heatmap.R +++ b/inst/examples/heatmap.R @@ -15,24 +15,48 @@ library(apexcharter) library(highcharter) # data library(dplyr) - - -# Data -------------------------------------------------------------------- - -data("vaccines") +library(tidyr) +# Mtcars heatmap ---------------------------------------------------------- -# Heatmap ----------------------------------------------------------------- - -#O trying to recreate "The Impact of Vaccines" (http://jkunst.com/highcharter/showcase.html) +mtcars_long <- mtcars %>% + tibble::rownames_to_column(var = "model") %>% + gather(variable, value, -model) apexchart() %>% ax_chart(type = "heatmap") %>% ax_dataLabels(enabled = FALSE) %>% + ax_series2(lapply( + X = unique(mtcars_long$model), + FUN = function(x) { + list( + name = x, + data = parse_df(mtcars_long[mtcars_long$model == x, c("variable", "value")]) + ) + } + )) %>% + ax_xaxis(type = "category", categories = unique(mtcars_long$variable)) + + + + + + +# Large Heatmap ----------------------------------------------------------- + +# pretty slow + +# trying to recreate "The Impact of Vaccines" (http://jkunst.com/highcharter/showcase.html) + +data("vaccines", package = "highcharter") + +apexchart() %>% + ax_chart(type = "heatmap", animations = list(enabled = FALSE)) %>% + ax_dataLabels(enabled = FALSE) %>% ax_series2(lapply( X = unique(vaccines$state), FUN = function(x) { diff --git a/inst/examples/proxy-update-serie-line.R b/inst/examples/proxy-update-serie-line.R new file mode 100644 index 0000000..6e09fe3 --- /dev/null +++ b/inst/examples/proxy-update-serie-line.R @@ -0,0 +1,47 @@ + +# ------------------------------------------------------------------------ +# +# Title : Update serie +# By : Victor +# Date : 2018-09-09 +# +# ------------------------------------------------------------------------ + + + +library(shiny) +library(apexcharter) + + + +ui <- fluidPage( + tags$h2("Radomly update serie"), + apexchartOutput(outputId = "graph", width = "600px"), + actionButton(inputId = "update", label = "Update data") +) + +server <- function(input, output, session) { + + output$graph <- renderApexchart({ + apexchart() %>% + ax_chart(type = "line") %>% + ax_plotOptions(line = list(curve = "smooth")) %>% + ax_dataLabels(enabled = FALSE) %>% + ax_series( + list( + name = "rnorm", + data = round(rnorm(20), 3) + ) + ) + }) + + observeEvent(input$update, { + apexchartProxy(shinyId = "graph") %>% + ax_proxy_series(newSeries = list(data = round(rnorm(20), 3))) + }) + +} + +shinyApp(ui, server) + + diff --git a/inst/htmlwidgets/apexcharter.js b/inst/htmlwidgets/apexcharter.js index d40a8ba..f3cd71f 100644 --- a/inst/htmlwidgets/apexcharter.js +++ b/inst/htmlwidgets/apexcharter.js @@ -66,11 +66,11 @@ function get_widget(id){ if (HTMLWidgets.shinyMode) { // data = load - Shiny.addCustomMessageHandler('update-apexcharts-series', + Shiny.addCustomMessageHandler('update-apexchart-series', function(obj) { - var chart = get_widget(data.id); + var chart = get_widget(obj.id); if (typeof chart != 'undefined') { - chart.updateSeries(obj.newSeries, obj.animate); + chart.updateSeries(obj.data.newSeries, obj.data.animate); } }); } diff --git a/man/apexchartProxy.Rd b/man/apexchartProxy.Rd new file mode 100644 index 0000000..ea54ab7 --- /dev/null +++ b/man/apexchartProxy.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/proxy.R +\name{apexchartProxy} +\alias{apexchartProxy} +\title{Proxy for \code{apexchart}} +\usage{ +apexchartProxy(shinyId, session = shiny::getDefaultReactiveDomain()) +} +\arguments{ +\item{shinyId}{single-element character vector indicating the output ID of the +chart to modify (if invoked from a Shiny module, the namespace will be added +automatically)} + +\item{session}{the Shiny session object to which the chart belongs; usually the +default value will suffice} +} +\description{ +Allow to update a chart in Shiny application. +} diff --git a/man/ax_proxy_series.Rd b/man/ax_proxy_series.Rd new file mode 100644 index 0000000..3577ead --- /dev/null +++ b/man/ax_proxy_series.Rd @@ -0,0 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/proxy.R +\name{ax_proxy_series} +\alias{ax_proxy_series} +\title{Proxy for updating series.} +\usage{ +ax_proxy_series(proxy, newSeries, animate = TRUE) +} +\arguments{ +\item{proxy}{A \code{apexchartProxy} \code{htmlwidget} object.} + +\item{newSeries}{The series array to override the existing one.} + +\item{animate}{Should the chart animate on re-rendering.} +} +\description{ +Allows you to update the series array overriding the existing one. +} +\examples{ +\dontrun{ + +if (interactive()) { + + + +} + +} +}