microsoft / datamations

https://microsoft.github.io/datamations/
Other
67 stars 14 forks source link

Figure out how to view vega/gemini renderings in R browser #22

Closed jhofman closed 3 years ago

jhofman commented 3 years ago

At some point we need to load the appropriate javascript libraries and pass data from R to html.

Can do so with files, but is there a better way (akin to r2d3)?

sharlagelfand commented 3 years ago

Moving the htmlwidgets discussion to here @jhofman @giorgi-ghviniashvili so it doesn't get lost in a conversation about Shiny apps.

I overwrote the bar chart shiny app with one that takes datamations frames, but here is how it works in a static R script (with info on how to install/run the app if you want)

library(dplyr)
library(palmerpenguins)
# Install code from branch (or just check it out)
# devtools::install_github("jhofman/datamations", ref = "vegalite-shiny")
library(datamations)

# Run app with 
datamations::run_app()

# Or just see output

mtcars %>%
  count(disp, name = "y") %>%
  rename(x = disp) %>%
  vegaliteBar()

visualization (1)

penguins %>%
  count(species, name = "y") %>%
  rename(x = species) %>%
  vegaliteBar()

visualization (2)

To explain the htmlwidgets structure....

  1. vegaliteBar() is an R function defined in R/vegaliteBar.R that takes the data as an argument and passes it immediately to the htmlwidgets framework to create a widget (named "vegaliteBar")
  2. inst/htmlwidgets/vegaliteBar.js is part of this framework - it takes the data passed from vegaliteBar(), converts it to the correct format, calls the barChart() js function on that data, and then embeds it in the element. The structure of this file is all predetermined by the htmlwidgets framework. It is also named "vegaliteBar" which is how the R and JS functions are connected.
  3. inst/htmlwidgets/barChart/barChart.js contains the barChart() function to actually create the vegalite bar chart from the data. This code is short enough that it could just be contained within vegaliteBar.js, but it'll probably be nice for us to separate out the code that creates the visualization from the code that creates the widget (above)
  4. inst/htmlwidgets/vegaliteBar.yaml defines all of the dependencies for the widget. They are stores locally in inst/htmlwidgets/

When you call vegaliteBar(), it renders the visualization in the RStudio viewer (a browser inside RStudio).

The ability to embed in a shiny app is just a given with the htmlwidgets structure - you create the widget with vegaliteBar(), render it in the server function as a "vegaliteBar" type, then put the output as a vegaliteBar type output in the UI. This idea of "render in the server" and "output in the UI" is the same for all Shiny apps, and automatically provided by the htmlwidgets framework.

Hope that is clear! Let me know if there's any questions.

jhofman commented 3 years ago

thanks for the great explanation of how this works @sharlagelfand!

giorgi-ghviniashvili commented 3 years ago

@sharlagelfand I just saw that you integrated my code into the shiny app in datamations-widget branch. Could you please help me run that shiny app locally (without devtools::install_github("jhofman/datamations", ref = "datamations-widget")?

sharlagelfand commented 3 years ago

@giorgi-ghviniashvili I'm still working on it, it's not fully functional yet unfortunately! But good spot 😄

This is just a widget that will be viewable in the RStudio viewer pane, not yet in any shiny app.

You can see where it is at so far though by running:

devtools::load_all() # to load the latest version of the code
datamationSandDance("test") # doesn't matter what the message is since it's not used, but has to have something
Screen Shot 2021-04-27 at 1 42 31 PM

You can open it in your browser by clicking the button outlined in red.

The animating doesn't work yet, but in case it's easier for you to inspect in the browser and figure out why than it would be for me, the HTML is defined here (this is what gives the div where the chart actually is a random ID) and the JS is all defined here.

giorgi-ghviniashvili commented 3 years ago

Thanks! I just did not know about devtools::load_all(), I set working directory to datamations and then it worked. Let me try to fix that widget or at least see how it works.

sharlagelfand commented 3 years ago

Sounds good! If you open the datamations.Rproj file, in RStudio it will set the working directory to be datamations by default when you are in that project, rather than having to set it

giorgi-ghviniashvili commented 3 years ago

It says that play() function not defined. If you call play() directly after init() datamationSandDance.js it will play it.

sharlagelfand commented 3 years ago

Have figured out getting the play() button working in this widget! Updated code is in the [datamations-widget branch]() - note that the JS for the widget is quite small, and it mostly calls external functions that do all the work. I've also updated init() and play() to take an ID so that we could have multiple widgets on a page, and the button would operate on the correct widget.

So this code produces a widget which can be played via the button:

datamationSandDance()

https://user-images.githubusercontent.com/15895337/116419572-30194080-a80b-11eb-983a-40cc42d2e2d4.mov

giorgi-ghviniashvili commented 3 years ago

@sharlagelfand this PR includes the simplified version of js, only play button. Removed slider and dataset name.

sharlagelfand commented 3 years ago

This widget is in an app now, you can select which of the specs to animate. This will likely converge with #23 sooner rather than later to use @giorgi-ghviniashvili's generalized animation engine shown here, but just an update on where the "gemini in R" bits are at!

jhofman commented 3 years ago

Closing this since I think the new issues cover what comes next.