Please note that most of the interactive plots below will not work properly when viewing this document as a web page. The first few examples below will work because it has been manually added in an iframe, but the others will not. If you want to see them in action, run the code in R.

Ggvis interactivity is built on top of Shiny’s reactive programming model. It’s possible to use ggvis without understanding how Shiny works, but you’ll be limited to relatively simple interactions. The first part of this vignette describes basic interactive controls, which provide a quick and easy way to add basic interactivity to a plot. They are not very flexible, but they cover the most common interactive needs and you don’t need to know anything about Shiny to use them.

The second part of this vignette shows you how to embedding a ggvis in a Shiny app. This gives you complete freedom to make any component of the plot interactive, to display multiple plots on one page, and to freely arrange controls. The downside is that you’ll need more code, and you’ll need at least a basic understanding of Shiny. If you’re not already familiar with how Shiny works, I recommend that you first read through the Shiny tutorial

Basic interactive controls

A plot with basic interactive controls looks very similar to a static plot. You just replace constant values with functions that produce interactive controls like input_slider():

ggvis(mtcars, props(x = ~wt, y = ~mpg)) +
  layer_smooth(span = input_slider(0.5, 1, 1, label = "span")) +
  layer_point(props(size := input_slider(100, 1000, label = "size")))

As well as input_slider(), which produces a slider (or a double-ended range slider), there are a number of other interactive controls:

Note that all interactive inputs start with input_ so that you can always use tab completion to remind you of the options.


The arguments differ slightly depending on the type of input, and are documented in the individual function documentation. All input sliders share three common arguments:

map is the most commonly argument used as it allows you to translate the value recieved from the input to something that’s meaningful for your plot. For example, many parameters of statistical models are best expressed on a log scale. You can use map in conjunction with an slider to make multiple orders of magnitude easily accessible from a single slider.

input_slider(-5, 5, label = "lambda", map = function(x) 10 ^ x)
#> <input> slider_694616554
#> sliderInput("slider_694616554", "lambda", min = -5, max = 5, 
#>     value = -5, step = NULL, round = FALSE, format = "#,##0.#####", 
#>     locale = "us", ticks = TRUE, animate = FALSE)

Multiple outputs

There are two ways to have an interactive input control multiple settings on the plot.

  1. Use the regular property inheritance structure:

    ggvis(mtcars, props(x = ~wt, y = ~mpg, size := input_slider(10, 1000, label = "size"))) +
      layer_point(props(fill := "red")) +
      layer_point(props(stroke := "black", fill := NA))
  1. Create the input and assign it to a variable:

    slider <- input_slider(10, 1000, label = "size")
    ggvis(mtcars, props(x = ~wt, y = ~mpg)) +
      layer_point(props(fill := "red", size := slider)) +
      layer_point(props(stroke := "black", fill := NA, size := slider))

    This is a little more typing, but is more flexible.

Compare the following two plots. In the first plot, one slider is created and used for both layers - it controls the size of both the red and the black points. In the second plot, you get two independent sliders which allow you to control the size of the red and black points independently.

slider <- input_slider(100, 1000)
ggvis(mtcars, props(x = ~wt, y = ~mpg)) +
  layer_point(props(size := slider)) +
  layer_point(props(fill := "red", opacity := 0.5, size := slider))
ggvis(mtcars, props(x = ~wt, y = ~mpg)) +
  layer_point(props(size := input_slider(100, 1000))) +
  layer_point(props(fill := "red", size := input_slider(100, 1000)))

Property mappings

When you map a slider to a property, you have four basic options:

If you just assign the input in props(), like props(size = input_slider()), you’ll get a constant, unscaled property. To gain more control you can use prop(): props(size = prop(input_slider())).

You’ll need to do this if you want to:

You can read more about these options in the properties and scales vignette.


Currently, interactive inputs can only be used in two places:

This means that interactive inputs can only modify the data, not the underlying plot specification. In other words, with only basic interactivity there’s no way to add or remove layers, or switch between different datasets. This is a reasonable limitation because if you’re doing exploration you can always create a new ggvis with R code, or if you’re polishing a plot for presentation, you can embed it in a Shiny app and gain full control over the plot.

Compared to Shiny

If you’re familiar with Shiny, you’ll notice that these functions have very similar equivalents: sliderInput(), selectInput() and so on. There are two main differences:

Shiny apps

If you know how to create a Shiny app already, adding a ggvis plot is easy. In server.r, create a reactive ggvis object, and call observeGgvis(). The first argument is the plot object, the second is the plot id (needs to match with ui.r, and the third argument is the session object).

gv <- reactive({
  ggvis(mtcars, props(x = ~disp, y = ~mpg, size := input$size)) +
observe_ggvis(gv, "my_plot", session)

Create ui.r as usual, using ggvisOutput() to place the ggvis plot on the page.

    sliderInput("size", "Area", 10, 1000),

There are a couple of examples in the demo/apps directory.