|
| 1 | +--- |
| 2 | +title: Shiny |
| 3 | +--- |
| 4 | + |
| 5 | +gglite charts can be embedded in [Shiny](https://shiny.posit.co/) applications |
| 6 | +using `render_shiny()`. Unlike `htmlwidgets`-based packages, gglite uses |
| 7 | +Shiny's custom message passing to send chart specs to the browser, where the G2 |
| 8 | +library renders them. |
| 9 | + |
| 10 | +## Setup |
| 11 | + |
| 12 | +Every Shiny app using gglite needs three script tags in the `<head>` of the UI: |
| 13 | + |
| 14 | +1. The G2 JavaScript library from a CDN. |
| 15 | +2. The gglite column-major data helper. |
| 16 | +3. The gglite Shiny message handler (`g2-handler.js`), bundled with the package. |
| 17 | + |
| 18 | +```r |
| 19 | +tags$head( |
| 20 | + tags$script(src = 'https://unpkg.com/@antv/g2@5/dist/g2.min.js'), |
| 21 | + tags$script( |
| 22 | + src = 'https://cdn.jsdelivr.net/npm/@xiee/utils/js/g2-column.min.js' |
| 23 | + ), |
| 24 | + includeScript(system.file('www/g2-handler.js', package = 'gglite')) |
| 25 | +) |
| 26 | +``` |
| 27 | + |
| 28 | +The container `<div>` must have an explicit height (G2 charts will not appear |
| 29 | +in a zero-height container) and an `id` that matches the `output_id` argument |
| 30 | +you pass to `render_shiny()`: |
| 31 | + |
| 32 | +```r |
| 33 | +div(id = 'my-chart', style = 'height:480px') |
| 34 | +``` |
| 35 | + |
| 36 | +## Basic Example |
| 37 | + |
| 38 | +The simplest app renders a static chart when the session starts. Call |
| 39 | +`render_shiny()` directly in the server function: |
| 40 | + |
| 41 | +```r |
| 42 | +library(shiny) |
| 43 | +library(gglite) |
| 44 | + |
| 45 | +ui = fluidPage( |
| 46 | + tags$head( |
| 47 | + tags$script(src = 'https://unpkg.com/@antv/g2@5/dist/g2.min.js'), |
| 48 | + tags$script( |
| 49 | + src = 'https://cdn.jsdelivr.net/npm/@xiee/utils/js/g2-column.min.js' |
| 50 | + ), |
| 51 | + includeScript(system.file('www/g2-handler.js', package = 'gglite')) |
| 52 | + ), |
| 53 | + div(id = 'chart1', style = 'height:480px') |
| 54 | +) |
| 55 | + |
| 56 | +server = function(input, output, session) { |
| 57 | + render_shiny( |
| 58 | + g2(mtcars, x = 'mpg', y = 'hp') |> mark_point(), |
| 59 | + session, 'chart1' |
| 60 | + ) |
| 61 | +} |
| 62 | + |
| 63 | +shinyApp(ui, server) |
| 64 | +``` |
| 65 | + |
| 66 | +## Reactive Example |
| 67 | + |
| 68 | +Wrap `render_shiny()` in `observeEvent()` (or `observe()`) to re-render the |
| 69 | +chart whenever an input changes. Pass `ignoreNULL = FALSE` so the chart also |
| 70 | +renders on startup. The following app lets the user pick the y-axis variable |
| 71 | +from a dropdown: |
| 72 | + |
| 73 | +```r |
| 74 | +library(shiny) |
| 75 | +library(gglite) |
| 76 | + |
| 77 | +ui = fluidPage( |
| 78 | + tags$head( |
| 79 | + tags$script(src = 'https://unpkg.com/@antv/g2@5/dist/g2.min.js'), |
| 80 | + tags$script( |
| 81 | + src = 'https://cdn.jsdelivr.net/npm/@xiee/utils/js/g2-column.min.js' |
| 82 | + ), |
| 83 | + includeScript(system.file('www/g2-handler.js', package = 'gglite')) |
| 84 | + ), |
| 85 | + selectInput('yvar', 'Y variable', choices = c('hp', 'wt', 'qsec', 'drat')), |
| 86 | + div(id = 'chart1', style = 'height:480px') |
| 87 | +) |
| 88 | + |
| 89 | +server = function(input, output, session) { |
| 90 | + observeEvent(input$yvar, { |
| 91 | + render_shiny( |
| 92 | + g2(mtcars, x = 'mpg', y = input$yvar) |> |
| 93 | + mark_point() |> |
| 94 | + title_of(input$yvar), |
| 95 | + session, 'chart1' |
| 96 | + ) |
| 97 | + }, ignoreNULL = FALSE) |
| 98 | +} |
| 99 | + |
| 100 | +shinyApp(ui, server) |
| 101 | +``` |
| 102 | + |
| 103 | +Each time the user picks a different variable, `render_shiny()` sends the |
| 104 | +updated spec to the browser and G2 re-renders the chart in place. |
| 105 | + |
| 106 | +## Multiple Charts |
| 107 | + |
| 108 | +You can render several charts independently by giving each container a distinct |
| 109 | +`id` and calling `render_shiny()` once per chart: |
| 110 | + |
| 111 | +```r |
| 112 | +library(shiny) |
| 113 | +library(gglite) |
| 114 | + |
| 115 | +ui = fluidPage( |
| 116 | + tags$head( |
| 117 | + tags$script(src = 'https://unpkg.com/@antv/g2@5/dist/g2.min.js'), |
| 118 | + tags$script( |
| 119 | + src = 'https://cdn.jsdelivr.net/npm/@xiee/utils/js/g2-column.min.js' |
| 120 | + ), |
| 121 | + includeScript(system.file('www/g2-handler.js', package = 'gglite')) |
| 122 | + ), |
| 123 | + fluidRow( |
| 124 | + column(6, div(id = 'scatter', style = 'height:400px')), |
| 125 | + column(6, div(id = 'bars', style = 'height:400px')) |
| 126 | + ) |
| 127 | +) |
| 128 | + |
| 129 | +server = function(input, output, session) { |
| 130 | + render_shiny( |
| 131 | + g2(mtcars, x = 'mpg', y = 'hp') |> mark_point(), |
| 132 | + session, 'scatter' |
| 133 | + ) |
| 134 | + freq = as.data.frame(table(cyl = mtcars$cyl)) |
| 135 | + render_shiny( |
| 136 | + g2(freq, x = 'cyl', y = 'Freq') |> mark_interval(), |
| 137 | + session, 'bars' |
| 138 | + ) |
| 139 | +} |
| 140 | + |
| 141 | +shinyApp(ui, server) |
| 142 | +``` |
0 commit comments