oz icon indicating copy to clipboard operation
oz copied to clipboard

Responsive plot render?

Open skallinen opened this issue 5 years ago • 6 comments

Thanks @metasoarous for this library, great work! Was playing with the library and one ux detail I was wondering about was whether the plot render could be responsive and take all the available real estate in the browser window where its rendered, unless something else is declared. Much the same way for instance ggplot does in ESS and I guess in RStudio as well.

skallinen avatar Aug 12 '19 19:08 skallinen

Hi @skallinen; Thanks for the feedback, and for raising this issue!

I'm not sure that I'd want for this automatic resizing to be the default behavior. In general, I want to stick to Vega/Vega-Lite default behavior wherever it makes sense. And while auto-resize certainly makes sense from an interactive perspective when viewing single plots, we have other use cases to keep in mind here; In particular, I'm wary of introducing too many difference in the way things render by default when viewing a single plot versus a document with multiple plots. To me, it's less surprising if single plots render with the same proportions as they would show up in an export or in a document.

That having been said, there is clearly value in being able to simply make plots take up all of the available screen real-estate. As @awb99 pointed out in #76, there's supposed to be some Vega/Vega-Lite magic for doing just this ("autosize": { "type": "fit" }), but the report is that this didn't work out of the box. It may be that the plot's container/div needs to have certain properties/styles for this to work properly (like width/height settings).

I have made responsive plots with Vega/Vega-Lite before (in https://github.com/matsengrp/olmsted), but we did it differently, by actually passing in width & height based on current window proportions, with a callback for hooking into screen resize events. If need be, we could potentially create a helper component/container here for accomplishing the same thing. But my preference would be to figure out a way for better accommodating the built in Vega/Vega-Lite features if possible.

Please feel free to experiment with these ideas and propose a course of action; Bottom line is that I agree this is something Oz should accommodate.

Thanks again!

metasoarous avatar Sep 29 '19 05:09 metasoarous

(This is using metasoarous/oz {:mvn/version "1.6.0-alpha15"})

I have managed to get the vega-lite magic for doing this to work by manually modifying the containing div in the browser, but I'm not sure how to add the required css styles from the hiccup syntax.

Minimal example - set the width property to "container":

(oz/start-server!)

(defn play-data [& names]
  (for [n names
        i (range 20)]
    {:time i :item n :quantity (+ (Math/pow (* i (count n)) 0.8) (rand-int (count n)))}))

(def line-plot
  {:data {:values (play-data "monkey" "slipper" "broom")}
   :encoding {:x {:field "time" :type "quantitative"}
              :y {:field "quantity" :type "quantitative"}
              :color {:field "item" :type "nominal"}}
   :mark "line"
   :width "container"})

(oz/view! line-plot)

Then (using browser tools) modify the style of the vega-lite div to have width: 100%:

<div class="viz vega-embed has-actions" role="graphics-document" aria-roledescription="visualization" aria-label="Vega visualization" style="cursor: default;width: 100%;">...</div>

The graph will update its size once the browser sends a size update event (e.g. resize the window).

To make this less clunky, we need some way to set the style (i.e. height and width) of the vega-lite div from the clojure side of things. My web dev is weak, but I couldn't get this to work by setting the style on a div containing the vega-lite div - I only got it to work when it was the vega-lite div itself that had the style set.

wongjoel avatar Aug 01 '20 02:08 wongjoel

Thanks @wongjoel for spending some time on this and reporting back! This is very helpful.

I think I should be able to add an option for this this specific use case, but perhaps also generally find a way to make it possible to pass styles to the div in question. I'll think a bit about this and get back to you.

Thanks again!

metasoarous avatar Aug 01 '20 17:08 metasoarous

Hmm... And thinking about this a bit, maybe this should be the default when viewing a single plot, vs a plot in the context of other content? Does that seem like a reasonable default?

metasoarous avatar Aug 01 '20 17:08 metasoarous

It seems reasonable enough to have the div set to width: 100% by default when viewing a single plot, since you still have to opt-in to the responsive plot render by adding :width "container" to the vega-lite spec. The main downside is see is that when the div is set to width: 100% and the vega-lite spec has a absolute width set, then the dropdown menu with "save as SVG, save as PNG etc." moves to the top right of the div even when the graph has a fixed size. screen screen2

Might look a bit strange in a few situations, but probably a quirk we can get used to if it allows us to get responsive plot renders more easily.

Interestingly, if we set the vega-lite div to width: 100% then enclose that inside another div with width: 50%, then the inner vega-lite div takes up 100% of the outer div which is 50% of the page, so there's a possible way forward when the plot is in the context of other content too...

wongjoel avatar Aug 02 '20 04:08 wongjoel

Thanks for your additional thoughts on this @wongjoel.

After some reflection, I think the right thing to do here is to just inspect the specification for whether or not either of the dimensions is set to container, and if so, specifically set the corresponding dimensions on the container div to 100%. We may have to take a bit of care to ensure there aren't any "gotchas" if someone tries to dynamically change these properties, but a) this use case seems largely uncommon, and b) I think we should be able to solve even this with judicious use of the react lifecycle methods in the reagent implementation.

This should be a pretty simple fix, so I'll try to get it wrapped up soon.

Thanks again!

metasoarous avatar Oct 04 '21 18:10 metasoarous