8

I've created a shiny dashboard which have a number of tabs each with a few plotly charts set side by side. Because they are side by side, it can be difficult to look into an individual chart in detail without zooming in on the browser for the chart to fill up the page (even then for some reason the chart bobs up and down when zoomed in).

I was thinking surely there must be a way in Plotly to create a button that creates a popup window of the chart which can be made full screen? However, I've searched on Google and can't find anything relevant to plotly.

I did find this... Shiny: plot results in popup window

This sort of pop-up window would suffice. But in this example the chart is only created on the pop-up window itself (and is an image rather than an interactive plot). What I would want to do in this case is mirror the chart on the main page, but I'm aware you calling the same output from two different parts of the UI doesn't work in Shiny.

Does anyone have any ideas on how to approach this?

Wolff
  • 1,051
  • 3
  • 18
  • 31
  • What about rendering a new output (different ID) from the same graph data in the pop-up/modalBox? – julien.leroux5 Sep 03 '21 at 09:26
  • I agree here with Julien. A large size modal with a new output in it (ggplot for example) you can have both graphics depending on same reactive function to provide the data, for example. – Miguel Suazo Sep 03 '21 at 19:31

1 Answers1

12
  1. No need to use a modal or any other additional components.
  2. No need to render it twice.
  3. We can solve this problem purely from front-end, no need of any sever handling.

Here is how We can do it with some CSS and js tricks:

library(shiny)
library(plotly)
ui <- fluidPage(
    htmltools::htmlDependencies(icon("")),
    tags$style(
        '
        .plot-zoom {
            position: absolute;
            border: none;
            background-color: transparent;
            bottom: 0;
            right: 0;

        }
        .full-screen {
            position: fixed;
            height: 98vh !important;
            width: 98vw !important;
            left: 0;
            top: 0;
            z-index: 9999;
            overflow: hidden;
        }
        '
    ),
    div(
        class = "plotly-full-screen",
        column(6, plotlyOutput("p2")),
        column(6, plotlyOutput("p1")),
    ),
    tags$script(HTML(
        "
        function plotZoom(el){
            el = $(el);
            var parent = el.parent().parent();
            if(el.attr('data-full_screen') === 'false') {
                parent.addClass('full-screen').trigger('resize').fadeOut().fadeIn();
                el.attr('data-full_screen', 'true');
            } else {
                parent.removeClass('full-screen').trigger('resize').fadeOut().fadeIn();
                el.attr('data-full_screen', 'false');
            }
        }
        
        $(function(){
           $('.plotly-full-screen  .plotly.html-widget').append(
            `
            <div style='position: relative;'>
                <button onclick=plotZoom(this) class='plot-zoom' data-full_screen='false' title='Full screen'>
                    <i class='fa fa-expand-arrows-alt'></i>
                </button>
            </div>
            `); 
        })
        "
    ))
   
)

server <- function(input, output, session) {
    output$p1 <- output$p2 <- renderPlotly(plot_ly(data = iris, x = ~Sepal.Length, y = ~Petal.Length))
}

shinyApp(ui, server)

I added a little button on the bottom-right of each plot. when it is clicked, the plot is zoomed to full screen and in full screen, click it again will go back to normal view.

how to use

  • All you need to do is place your plot components inside a parent or grandparent or grand-grand...parent component which has class = "plotly-full-screen".
  • Change the .plot-zoom style if you don't like the button position or color etc.
  • Another good thing is when you use the plotly screenshot button, this full screen button will not be included.
  • Include the style and script tags in your app. Usually you want to have the style close to the top (head) of your app and place the script after plot tags.

Before zoom enter image description here

After zoom enter image description here

Enjoy!

lz100
  • 6,990
  • 6
  • 29