Usage with R markdown and shiny
1. Embed a sketch R file in R Markdown document
Suppose the sketch R file is sketch.R
, then it can be embedded in an
RMD file using sketch::insert_sketch
in a code chunk:
sketch::insert_sketch(file = "sketch.R", width = 800, height = 600)
2. Using sketch code in shiny
Use compile_r
to turn a sketch R file into a JavaScript file, copy it
into the www
folder of the shiny App, then include the script tag
tags$script(src = ...)
in the shiny UI.
2.1. A full example
Here is an example of shiny App with and without sketch code.
The advantage of using sketch is that it gives you complete control of the JavaScript behaviour, but the disadvantage is of course that more work is needed to achieve such control.
2.2. Source code
app.R
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
tags$head(tags$script(src="https://cdn.plot.ly/plotly-latest.min.js")),
titlePanel("Old Faithful Geyser Data"),
mainPanel(
tags$script(src="dom.js"),
tags$script(src="slider.js"),
tags$script(src="plot.js"),
)
)
# Define server logic required to draw a histogram
server <- function(input, output, session) {
# Send data for plotting the histogram at the start
session$sendCustomMessage(
"hist_data",
list(x = faithful$eruptions, probability = TRUE,
xlab = "Duration (minutes)",
main = "Geyser eruption duration")
)
# When a slider value is received, send the density values over
observeEvent(input$slider_value, {
cat("\nMessage received\n")
print(input$slider_value)
bw_adjust <- as.numeric(input$slider_value$data)
dens <- density(faithful$eruptions, adjust = bw_adjust)
session$sendCustomMessage("den_data", dens)
})
}
# Run the application
shinyApp(ui = ui, server = server)
dom.R
dom.R
is provided by the package, and the file path can be found using
src("dom")
. Suppose you are at the shiny App directory, in which there
is an www
folder, then dom.js
can be generated by running
compile_r(
input = src("dom"), output = "./www/dom.js",
rules = basic_rules(), deparsers = basic_deparsers()
)
slider.R
# Create a bare bone slider
container <- dom("div", list(id = "slider_1"))
label <- dom("label", list(innerText = "Bandwidth adjustment:"))
slider <- dom("input", list(type = "range", min = 0.2, max = 2,
value = 1, step = 0.01, style = "width: 480px"))
# Send commands to R when the slider changes
slider$oninput <- function() {
# Use method provided by the Shiny object
Shiny$onInputChange("slider_value", list(bw_adjust = self$value))
}
print_dom(container, ".col-sm-8")
print_dom(label, "#slider_1")
print_dom(slider, "#slider_1")
Generate slider.js
using the following command:
compile_r(
input = "slider.R", output = "./www/slider.js",
rules = basic_rules(), deparsers = basic_deparsers()
)
plot.R
hist_container <- dom("div", list(id = "myDiv", style = "width: 500px"))
print_dom(hist_container, ".col-sm-8")
# Histogram plot
hist <- function(msg, at = "myDiv") {
declare (data, layout)
data <- list(x = msg$x, type = "histogram",
histnorm = ifelse(msg$probability, "probability density", "count"),
marker = list(color = "rgb(200, 200, 200)",
line = list(color = "rgb(0, 0, 0)", width = 1)))
layout <- list(title = msg$main,
xaxis = list(title = msg$xlab),
yaxis = list(title = ifelse(msg$probability, "Density", "Frequency")),
showlegend = FALSE)
Plotly::newPlot(at, Array(data), layout)
}
Shiny$addCustomMessageHandler("hist_data", hist)
# Density plot
trace_exists <- FALSE
density <- function(msg, at = "myDiv") {
declare (data)
data <- list(x = msg$x, y = msg$y, type = "scatter", showlegend = FALSE)
if (!trace_exists) { # Add trace if not existed
Plotly::addTraces(at, data)
trace_exists <- TRUE
} else { # Update trace if existed
Plotly::deleteTraces(at, -1)
Plotly::addTraces(at, data)
}
}
Shiny$addCustomMessageHandler("den_data", density)
Generate plot.js
using the following command:
compile_r(
input = "plot.R", output = "./www/plot.js",
rules = basic_rules(), deparsers = basic_deparsers()
)