microsoft / datamations

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

Save output animation to file #99

Closed joelostblom closed 2 years ago

joelostblom commented 2 years ago

Thanks for the work on this library, it looks really cool and I am looking forward to incorporating it in my data viz teaching!

I am wondering if there are any options to redirect the output to a file programatically, either .html or .gif would work great for my purposes.

sharlagelfand commented 2 years ago

Thanks @joelostblom!

We don't have an option to output to a .gif right now but I can definitely see the need for that - especially since I've been manually converting the datamations to GIFs for the documentation!

To output to .html, you can use the save_html() function from the htmltools package, e.g.

library(dplyr)
library(datamations)
library(htmltools)

"small_salary %>% 
  group_by(Degree) %>%
  summarize(mean = mean(Salary))" %>%
  datamation_sanddance() %>%
  save_html("small_salary.html")

will output the datamation into a file called small_salary.html.

Hope that helps for now! Saving to .gif should definitely be on our roadmap though 🎥 I'll tag this issue appropriately.

jhofman commented 2 years ago

@giorgi-ghviniashvili will follow up with gemini to ask if there's a way to do this without having to manually screenshot videos.

if it's not supported in any way, one idea would be to monitor the part of the DOM that contains the datamation for changes and grab a snapshot of each rendered frame to a png or jpeg, then stitch to a gif.

sharlagelfand commented 2 years ago

Just thinking, it would probably be helpful to even be able to export each of the frames individually, so that they can e.g. be laid out all together on a page or gif'd together really slowly, even without considering the animations!

giorgi-ghviniashvili commented 2 years ago

@sharlagelfand yes, that would be useful, but for the gif we will need intermediate screenshots I think. Here is the issue I posted on gemini's github:

sharlagelfand commented 2 years ago

Yes definitely @giorgi-ghviniashvili - but leaving the GIF out of it, each "step" is a valid vega lite spec that we could output

jhofman commented 2 years ago

neat idea on grabbing each frame as a vegalite spec. if possible that would be pretty neat / cool.

if not, then maybe an approach like these?

https://observablehq.com/@mbostock/canvas-to-gif https://bl.ocks.org/veltman/1071413ad6b5b542a1a3

or one of the alternatives here? https://github.com/veltman/gifs

jhofman commented 2 years ago

Sounds like we might be headed towards 3 different ways of outputting things:

  1. PNGs of rendered key frames (a handful of frames)
  2. PNGs of all frames in the animation (more like hundreds or thousands of frames)
  3. A GIF version of the above, which should be easy once the PNGs are created
  4. Vega specs for key frames (@giorgi-ghviniashvili already has an array containing this, although custom css / hacks could complicate this)
giorgi-ghviniashvili commented 2 years ago

@jhofman btw, vega-lite has this details popup which is able to export visualization as png or svg. I hid it because it will not work properly when we hack facets. But it just works when there is meta: {axes: false}.

image

giorgi-ghviniashvili commented 2 years ago

I made a solution that will just download all frames as pngs. This will also work for hacked facets.

https://user-images.githubusercontent.com/6615532/140482851-08997a4c-71ef-4cc1-af5e-99f525faa1e3.mov

jhofman commented 2 years ago

Awesome!

Note: the gemini editor has an export as GIF button, perhaps we can learn something about how it works?

giorgi-ghviniashvili commented 2 years ago

@jhofman managed to export gif using gifshot.

https://user-images.githubusercontent.com/6615532/145032703-daeffdd0-0ec4-4181-b858-15982b319781.mov

jhofman commented 2 years ago

Is there a way to render and save the GIF within an R script by "hiding" the viewer window or something like that?

jhofman commented 2 years ago

this might be trickier than we thought.

@giorgi-ghviniashvili will check if there's a way to generate the gif from a node command line script or equivalent (could require a headless browser, which would be complicated.)

if it's really tricky we put this on the back burner.

giorgi-ghviniashvili commented 2 years ago

@jhofman managed to export gif from command line using headless chrome. Thanks to puppeteer.

From R, we need to first run Shiny app, set the url or even pass url to the node.js script and then run this node.js script that is in the video.

https://user-images.githubusercontent.com/6615532/149141092-484238a4-c5b5-4ed1-8f6e-f1492cbe062a.mov

jhofman commented 2 years ago

it's great that this is working.

now we have to decide the interface to exporting a GIF. it relies on having a running page somewhere that puppeteer connects to and runs the exportGif() function. this okay but would be nice to streamline.

it seems there are two basic use cases. one where you're in R or Python and want to save what you're doing, and another where you're at the command line, potentially.

thinking about the first use case, it could be that the use runs datamations in R and gets a result in the Viewer window, and then puppeteer connects to that local server to grab the GIF.

let's push this decision off a week or two once we're back into R development.

p.s. also, the GIFs are rendering a bit fast so we need to adjust the number of frames.

jhofman commented 2 years ago

@giorgi-ghviniashvili, let's try this: a command line node tool that has the following interface:

then we can call this from the R side with a system() command

jhofman commented 2 years ago

@giorgi-ghviniashvili, once the big PR is done, can you see if you can get the "export gif" button into the web version?

giorgi-ghviniashvili commented 2 years ago

@jhofman I made this work. PR is not merged yet, and I think I will have this as part of PR as well.

This animation.gif is exported.

animation

jhofman commented 2 years ago

done as of #146