如何将绘图复制到剪贴板以进行粘贴?
How to copy a plot into the clipboard for pasting?
在 运行 下面的可重现代码中,用户可以 select 通过单击呈现的 Shiny 顶部的单选按钮来查看实际数据或数据图屏幕(如编码所示,默认为数据)。在渲染屏幕的底部,您会看到一个“复制”按钮。通过select输入“数据”然后“复制”,您可以轻松地将数据粘贴到 XLS 中。
但是,如果用户改为 select 查看剧情,我希望用户也能够 copy/paste 以相同的方式查看剧情。如何做到这一点?
我试过在下面 observeEvent(...)
的 capture.output(...)
函数(及其各种迭代)中插入 plotPNG(...)
,使用由条件 if input$view == 'Plot'
触发的条件, 但还没有运气。
library(shiny)
library(ggplot2)
ui <- fluidPage(
radioButtons("view",
label = "View data or plot",
choiceNames = c('Data','Plot'),
choiceValues = c('Data','Plot'),
selected = 'Data',
inline = TRUE
),
conditionalPanel("input.view == 'Data'",tableOutput("DF")),
conditionalPanel("input.view == 'Plot'",plotOutput("plotDF")),
actionButton("copy","Copy",style = "width:20%;")
)
server <- function(input, output, session) {
data <- data.frame(Period = c(1,2,3,4,5,6),Value = c(10,20,15,40,35,30))
output$DF <- renderTable(data)
output$plotDF <- renderPlot(ggplot(data, aes(Period,Value)) + geom_line())
observeEvent(
req(input$copy),
writeLines(
capture.output(
write.table(
x = data,
sep = "\t",
row.names = FALSE
)
),
"clipboard")
)
}
shinyApp(ui, server)
你可以试试shinyscreenshot
:你可以进一步调整它https://daattali.com/shiny/shinyscreenshot-demo/
这是一个例子:
library(shiny)
library(ggplot2)
library(shinyscreenshot)
ui <- fluidPage(
radioButtons("view",
label = "View data or plot",
choiceNames = c('Data','Plot'),
choiceValues = c('Data','Plot'),
selected = 'Data',
inline = TRUE
),
div(
id = "takemyscreenshot",
conditionalPanel("input.view == 'Data'",tableOutput("DF")),
conditionalPanel("input.view == 'Plot'",plotOutput("plotDF")),
actionButton("go","Go",style = "width:20%;")
)
)
server <- function(input, output, session) {
observeEvent(input$go, {
screenshot(id = "takemyscreenshot")
})
data <- data.frame(Period = c(1,2,3,4,5,6),Value = c(10,20,15,40,35,30))
output$DF <- renderTable(data)
output$plotDF <- renderPlot(ggplot(data, aes(Period,Value)) + geom_line())
observeEvent(
req(input$copy),
writeLines(
capture.output(
write.table(
x = data,
sep = "\t",
row.names = FALSE
)
),
"clipboard")
)
}
shinyApp(ui, server)
已在 Edge 上测试。
library(shiny)
library(ggplot2)
js <- '
async function getImageBlobFromUrl(url) {
const fetchedImageData = await fetch(url);
const blob = await fetchedImageData.blob();
return blob;
}
$(document).ready(function () {
$("#copybtn").on("click", async () => {
const src = $("#plotDF>img").attr("src");
try {
const blob = await getImageBlobFromUrl(src);
await navigator.clipboard.write([
new ClipboardItem({
[blob.type]: blob
})
]);
alert("Image copied to clipboard!");
} catch (err) {
console.error(err.name, err.message);
alert("There was an error while copying image to clipboard :/");
}
});
});
'
ui <- fluidPage(
tags$head(
tags$script(HTML(js))
),
br(),
actionButton("copybtn", "Copy", icon = icon("copy"), class = "btn-primary"),
br(),
plotOutput("plotDF")
)
server <- function(input, output, session){
output[["plotDF"]] <- renderPlot({
ggplot(
iris, aes(x = Sepal.Length, y = Sepal.Width)
) + geom_point()
})
}
shinyApp(ui, server)
编辑
警报不是很好。我建议改为 shinyToastify。
library(shiny)
library(shinyToastify)
library(ggplot2)
js <- '
async function getImageBlobFromUrl(url) {
const fetchedImageData = await fetch(url);
const blob = await fetchedImageData.blob();
return blob;
}
$(document).ready(function () {
$("#copybtn").on("click", async () => {
const src = $("#plotDF>img").attr("src");
try {
const blob = await getImageBlobFromUrl(src);
await navigator.clipboard.write([
new ClipboardItem({
[blob.type]: blob
})
]);
Shiny.setInputValue("success", true, {priority: "event"});
} catch (err) {
console.error(err.name, err.message);
Shiny.setInputValue("failure", true, {priority: "event"});
}
});
});
'
ui <- fluidPage(
tags$head(
tags$script(HTML(js))
),
useShinyToastify(),
br(),
actionButton("copybtn", "Copy", icon = icon("copy"), class = "btn-primary"),
br(),
plotOutput("plotDF")
)
server <- function(input, output, session){
output[["plotDF"]] <- renderPlot({
ggplot(
iris, aes(x = Sepal.Length, y = Sepal.Width)
) + geom_point()
})
observeEvent(input[["success"]], {
showToast(
session,
input,
text = tags$span(
style = "color: white; font-size: 20px;", "Image copied!"
),
type = "success",
position = "top-center",
autoClose = 3000,
pauseOnFocusLoss = FALSE,
draggable = FALSE,
style = list(
border = "4px solid crimson",
boxShadow = "rgba(0, 0, 0, 0.56) 0px 22px 30px 4px"
)
)
})
observeEvent(input[["failure"]], {
showToast(
session,
input,
text = tags$span(
style = "color: white; font-size: 20px;", "Failed to copy image!"
),
type = "error",
position = "top-center",
autoClose = 3000,
pauseOnFocusLoss = FALSE,
draggable = FALSE,
style = list(
border = "4px solid crimson",
boxShadow = "rgba(0, 0, 0, 0.56) 0px 22px 30px 4px"
)
)
})
}
shinyApp(ui, server)
在 运行 下面的可重现代码中,用户可以 select 通过单击呈现的 Shiny 顶部的单选按钮来查看实际数据或数据图屏幕(如编码所示,默认为数据)。在渲染屏幕的底部,您会看到一个“复制”按钮。通过select输入“数据”然后“复制”,您可以轻松地将数据粘贴到 XLS 中。
但是,如果用户改为 select 查看剧情,我希望用户也能够 copy/paste 以相同的方式查看剧情。如何做到这一点?
我试过在下面 observeEvent(...)
的 capture.output(...)
函数(及其各种迭代)中插入 plotPNG(...)
,使用由条件 if input$view == 'Plot'
触发的条件, 但还没有运气。
library(shiny)
library(ggplot2)
ui <- fluidPage(
radioButtons("view",
label = "View data or plot",
choiceNames = c('Data','Plot'),
choiceValues = c('Data','Plot'),
selected = 'Data',
inline = TRUE
),
conditionalPanel("input.view == 'Data'",tableOutput("DF")),
conditionalPanel("input.view == 'Plot'",plotOutput("plotDF")),
actionButton("copy","Copy",style = "width:20%;")
)
server <- function(input, output, session) {
data <- data.frame(Period = c(1,2,3,4,5,6),Value = c(10,20,15,40,35,30))
output$DF <- renderTable(data)
output$plotDF <- renderPlot(ggplot(data, aes(Period,Value)) + geom_line())
observeEvent(
req(input$copy),
writeLines(
capture.output(
write.table(
x = data,
sep = "\t",
row.names = FALSE
)
),
"clipboard")
)
}
shinyApp(ui, server)
你可以试试shinyscreenshot
:你可以进一步调整它https://daattali.com/shiny/shinyscreenshot-demo/
这是一个例子:
library(shiny)
library(ggplot2)
library(shinyscreenshot)
ui <- fluidPage(
radioButtons("view",
label = "View data or plot",
choiceNames = c('Data','Plot'),
choiceValues = c('Data','Plot'),
selected = 'Data',
inline = TRUE
),
div(
id = "takemyscreenshot",
conditionalPanel("input.view == 'Data'",tableOutput("DF")),
conditionalPanel("input.view == 'Plot'",plotOutput("plotDF")),
actionButton("go","Go",style = "width:20%;")
)
)
server <- function(input, output, session) {
observeEvent(input$go, {
screenshot(id = "takemyscreenshot")
})
data <- data.frame(Period = c(1,2,3,4,5,6),Value = c(10,20,15,40,35,30))
output$DF <- renderTable(data)
output$plotDF <- renderPlot(ggplot(data, aes(Period,Value)) + geom_line())
observeEvent(
req(input$copy),
writeLines(
capture.output(
write.table(
x = data,
sep = "\t",
row.names = FALSE
)
),
"clipboard")
)
}
shinyApp(ui, server)
已在 Edge 上测试。
library(shiny)
library(ggplot2)
js <- '
async function getImageBlobFromUrl(url) {
const fetchedImageData = await fetch(url);
const blob = await fetchedImageData.blob();
return blob;
}
$(document).ready(function () {
$("#copybtn").on("click", async () => {
const src = $("#plotDF>img").attr("src");
try {
const blob = await getImageBlobFromUrl(src);
await navigator.clipboard.write([
new ClipboardItem({
[blob.type]: blob
})
]);
alert("Image copied to clipboard!");
} catch (err) {
console.error(err.name, err.message);
alert("There was an error while copying image to clipboard :/");
}
});
});
'
ui <- fluidPage(
tags$head(
tags$script(HTML(js))
),
br(),
actionButton("copybtn", "Copy", icon = icon("copy"), class = "btn-primary"),
br(),
plotOutput("plotDF")
)
server <- function(input, output, session){
output[["plotDF"]] <- renderPlot({
ggplot(
iris, aes(x = Sepal.Length, y = Sepal.Width)
) + geom_point()
})
}
shinyApp(ui, server)
编辑
警报不是很好。我建议改为 shinyToastify。
library(shiny)
library(shinyToastify)
library(ggplot2)
js <- '
async function getImageBlobFromUrl(url) {
const fetchedImageData = await fetch(url);
const blob = await fetchedImageData.blob();
return blob;
}
$(document).ready(function () {
$("#copybtn").on("click", async () => {
const src = $("#plotDF>img").attr("src");
try {
const blob = await getImageBlobFromUrl(src);
await navigator.clipboard.write([
new ClipboardItem({
[blob.type]: blob
})
]);
Shiny.setInputValue("success", true, {priority: "event"});
} catch (err) {
console.error(err.name, err.message);
Shiny.setInputValue("failure", true, {priority: "event"});
}
});
});
'
ui <- fluidPage(
tags$head(
tags$script(HTML(js))
),
useShinyToastify(),
br(),
actionButton("copybtn", "Copy", icon = icon("copy"), class = "btn-primary"),
br(),
plotOutput("plotDF")
)
server <- function(input, output, session){
output[["plotDF"]] <- renderPlot({
ggplot(
iris, aes(x = Sepal.Length, y = Sepal.Width)
) + geom_point()
})
observeEvent(input[["success"]], {
showToast(
session,
input,
text = tags$span(
style = "color: white; font-size: 20px;", "Image copied!"
),
type = "success",
position = "top-center",
autoClose = 3000,
pauseOnFocusLoss = FALSE,
draggable = FALSE,
style = list(
border = "4px solid crimson",
boxShadow = "rgba(0, 0, 0, 0.56) 0px 22px 30px 4px"
)
)
})
observeEvent(input[["failure"]], {
showToast(
session,
input,
text = tags$span(
style = "color: white; font-size: 20px;", "Failed to copy image!"
),
type = "error",
position = "top-center",
autoClose = 3000,
pauseOnFocusLoss = FALSE,
draggable = FALSE,
style = list(
border = "4px solid crimson",
boxShadow = "rgba(0, 0, 0, 0.56) 0px 22px 30px 4px"
)
)
})
}
shinyApp(ui, server)