我创建了一个闪亮的仪表板,其中有许多选项卡,每个选项卡都并排设置了一些绘图图表。因为它们是并排的,所以如果不放大浏览器以使图表填满页面,就很难详细查看单个图表(即使如此,由于某种原因,图表在放大时会上下摆动)。
我在想 Plotly 中肯定有一种方法可以创建一个按钮来创建一个可以全屏显示的图表弹出窗口?然而,我在谷歌上搜索过,找不到任何与plotly相关的内容。
我确实找到了这个... Shiny:在弹出窗口中绘制结果
这种弹窗就够了。但在本例中,图表仅在弹出窗口本身上创建(并且是图像而不是交互式绘图)。在这种情况下,我想做的是镜像主页上的图表,但我知道您从 UI 的两个不同部分调用相同的输出在 Shiny 中不起作用。
有人对如何解决这个问题有任何想法吗?
我们可以通过一些 CSS 和 js 技巧来做到这一点:
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)
我在每个图的右下角添加了一个小按钮。单击时,绘图将放大到全屏,在全屏状态下,再次单击将返回正常视图。
class = "plotly-full-screen"
的父组件或祖父母或曾祖...父组件中。.plot-zoom
样式。style
和 script
标签。通常您希望样式靠近应用程序的顶部(头部),并将脚本放置在绘图标签之后。享受吧!
受上面启发,但使用绘图菜单栏加上一个额外的 csv 下载按钮。分享回来,因为它对我有帮助。
library(shiny)
library(plotly)
# SVG icons
icons <- list()
# Fullscreen (source : https://fontawesome.com/icons/expand?f=classic&s=solid)
icons$expand <- "M32 32C14.3 32 0 46.3 0 64v96c0 17.7 14.3 32 32 32s32-14.3 32-32V96h64c17.7 0 32-14.3 32-32s-14.3-32-32-32H32zM64 352c0-17.7-14.3-32-32-32s-32 14.3-32 32v96c0 17.7 14.3 32 32 32h96c17.7 0 32-14.3 32-32s-14.3-32-32-32H64V352zM320 32c-17.7 0-32 14.3-32 32s14.3 32 32 32h64v64c0 17.7 14.3 32 32 32s32-14.3 32-32V64c0-17.7-14.3-32-32-32H320zM448 352c0-17.7-14.3-32-32-32s-32 14.3-32 32v64H320c-17.7 0-32 14.3-32 32s14.3 32 32 32h96c17.7 0 32-14.3 32-32V352z"
# Download Data CSV (source : https://fontawesome.com/icons/file-csv?f=classic&s=solid)
icons$csv <- "M0 64C0 28.7 28.7 0 64 0H224V128c0 17.7 14.3 32 32 32H384V304H176c-35.3 0-64 28.7-64 64V512H64c-35.3 0-64-28.7-64-64V64zm384 64H256V0L384 128zM200 352h16c22.1 0 40 17.9 40 40v8c0 8.8-7.2 16-16 16s-16-7.2-16-16v-8c0-4.4-3.6-8-8-8H200c-4.4 0-8 3.6-8 8v80c0 4.4 3.6 8 8 8h16c4.4 0 8-3.6 8-8v-8c0-8.8 7.2-16 16-16s16 7.2 16 16v8c0 22.1-17.9 40-40 40H200c-22.1 0-40-17.9-40-40V392c0-22.1 17.9-40 40-40zm133.1 0H368c8.8 0 16 7.2 16 16s-7.2 16-16 16H333.1c-7.2 0-13.1 5.9-13.1 13.1c0 5.2 3 9.9 7.8 12l37.4 16.6c16.3 7.2 26.8 23.4 26.8 41.2c0 24.9-20.2 45.1-45.1 45.1H304c-8.8 0-16-7.2-16-16s7.2-16 16-16h42.9c7.2 0 13.1-5.9 13.1-13.1c0-5.2-3-9.9-7.8-12l-37.4-16.6c-16.3-7.2-26.8-23.4-26.8-41.2c0-24.9 20.2-45.1 45.1-45.1zm98.9 0c8.8 0 16 7.2 16 16v31.6c0 23 5.5 45.6 16 66c10.5-20.3 16-42.9 16-66V368c0-8.8 7.2-16 16-16s16 7.2 16 16v31.6c0 34.7-10.3 68.7-29.6 97.6l-5.1 7.7c-3 4.5-8 7.1-13.3 7.1s-10.3-2.7-13.3-7.1l-5.1-7.7c-19.3-28.9-29.6-62.9-29.6-97.6V368c0-8.8 7.2-16 16-16z"
dirty_js <- function(x) {
structure(x, class = unique(c("JS_EVAL", oldClass(x))))
}
button_fullscreen <- function() {
list(
name = "fullscreen",
title = "Toggle fullscreen",
icon = list(
path = icons$expand,
transform = 'matrix(1 0 0 1 0 -1) scale(0.03571429)'
),
attr = "full_screen",
val = "false",
click = dirty_js(
"function(gd, ev) {
var button = ev.currentTarget;
var astr = button.getAttribute('data-attr');
var val = button.getAttribute('data-val') || false;
if(astr === 'full_screen') {
if(val === 'false') {
button.setAttribute('data-val', 'true');
gd.classList.add('full-screen');
Plotly.Plots.resize(gd);
} else {
button.setAttribute('data-val', 'false');
gd.classList.remove('full-screen');
Plotly.Plots.resize(gd);
}
}
}"
)
)
}
dirty_csv <- function(data) {
c(
paste0(colnames(data), collapse = ","),
apply(data, 1, paste0, collapse = ",")
) |> paste0(collapse = "\n") |> utils::URLencode(reserved = TRUE)
}
button_download <- function(data) {
list(
name = "datacsv",
title = "Download plot data as csv",
icon = list(
path = icons$csv,
transform = 'matrix(1 0 0 1 0 0) scale(0.03125)'
),
click = dirty_js(
"function(gd, ev) {
var el = document.createElement('a');
el.setAttribute('href', 'data:text/plain;charset=utf-8,%s');
el.setAttribute('download', 'plot_data.csv');
el.click();
}" |> sprintf(dirty_csv(data))
)
)
}
ui <- fluidPage(
tags$style(
'
.full-screen {
position: fixed;
height: 98vh !important;
width: 98vw !important;
left: 0;
top: 0;
z-index: 9999;
overflow: hidden;
}
'
),
div(
column(6, plotlyOutput("p2")),
column(6, plotlyOutput("p1")),
)
)
server <- function(input, output, session) {
p <- plot_ly(data = iris, x = ~Sepal.Length, y = ~Petal.Length)
p <- config(
p,
modeBarButtonsToAdd = list(
list(button_fullscreen(), button_download(p[["x"]][["visdat"]][[p[["x"]][["cur_data"]]]]()))
),
modeBarButtonsToRemove = c("toImage", "hoverClosest","hoverCompare"),
displaylogo = FALSE
)
output$p1 <- output$p2 <- renderPlotly(p)
}
shinyApp(ui, server)