我以 Joe 的回答为基础解决了他的解决方案的局限性
- 使用 Plotly.toImage 而不是 Plotly.Snapshot.toImage 使用户能够通过 toImageButtonOptions 选择复制的绘图大小或默认为闪亮应用中显示的任何大小。
- 添加了 svg 复制图标
限制:
- 仅适用于 localhost 或 shinyapps.io 或 shiny server pro,因为所有浏览器都会阻止剪贴板访问,除非网站使用 HTTPS 或 localhost
library(tidyverse)
library(plotly)
# only works in shinyapps.io or localhost due to all browsers only allowing clipboard access over HTTPS or localhost
plotly_add_copy_button <- function(pl) {
# can also be htmlwidgets::JS("Plotly.Icons.disk")
# download svg from eg https://uxwing.com/files-icon/
icon_copy_svg <- list(
path = str_c(
"M102.17,29.66A3,3,0,0,0,100,26.79L73.62,1.1A3,3,0,0,0,71.31,0h-46a5.36,5.36,0,0,0-5.36,5.36V20.41H5.36A5.36,5.36,0,0,0,0,25.77v91.75a5.36,",
"5.36,0,0,0,5.36,5.36H76.9a5.36,5.36,0,0,0,5.33-5.36v-15H96.82a5.36,5.36,0,0,0,5.33-5.36q0-33.73,0-67.45ZM25.91,20.41V6h42.4V30.24a3,3,0,0,0,",
"3,3H96.18q0,31.62,0,63.24h-14l0-46.42a3,3,0,0,0-2.17-2.87L53.69,21.51a2.93,2.93,0,0,0-2.3-1.1ZM54.37,30.89,72.28,47.67H54.37V30.89ZM6,116.89V26.",
"37h42.4V50.65a3,3,0,0,0,3,3H76.26q0,31.64,0,63.24ZM17.33,69.68a2.12,2.12,0,0,1,1.59-.74H54.07a2.14,2.14,0,0,1,1.6.73,2.54,2.54,0,0,1,.63,1.7,2.",
"57,2.57,0,0,1-.64,1.7,2.16,2.16,0,0,1-1.59.74H18.92a2.15,2.15,0,0,1-1.6-.73,2.59,2.59,0,0,1,0-3.4Zm0,28.94a2.1,2.1,0,0,1,1.58-.74H63.87a2.12,2.12,",
"0,0,1,1.59.74,2.57,2.57,0,0,1,.64,1.7,2.54,2.54,0,0,1-.63,1.7,2.14,2.14,0,0,1-1.6.73H18.94a2.13,2.13,0,0,1-1.59-.73,2.56,2.56,0,0,1,0-3.4ZM63.87,83.",
"41a2.12,2.12,0,0,1,1.59.74,2.59,2.59,0,0,1,0,3.4,2.13,2.13,0,0,1-1.6.72H18.94a2.12,2.12,0,0,1-1.59-.72,2.55,2.55,0,0,1-.64-1.71,2.5,2.5,0,0,1,.65",
"-1.69,2.1,2.1,0,0,1,1.58-.74ZM17.33,55.2a2.15,2.15,0,0,1,1.59-.73H39.71a2.13,2.13,0,0,1,1.6.72,2.61,2.61,0,0,1,0,3.41,2.15,2.15,0,0,1-1.59.73H18.92a2.",
"14,2.14,0,0,1-1.6-.72,2.61,2.61,0,0,1,0-3.41Zm0-14.47A2.13,2.13,0,0,1,18.94,40H30.37a2.12,2.12,0,0,1,1.59.72,2.61,2.61,0,0,1,0,3.41,2.13,2.13,0,0,1-1.58.",
"73H18.94a2.16,2.16,0,0,1-1.59-.72,2.57,2.57,0,0,1-.64-1.71,2.54,2.54,0,0,1,.65-1.7ZM74.3,10.48,92.21,27.26H74.3V10.48Z"
),
transform = 'scale(0.12)'
)
plotly_copy_button <- list(
name = "Copy to Clipboard",
icon = icon_copy_svg,
click = htmlwidgets::JS('function(gd) {copyPlot(gd)}') # JS function defined by us and added in ui.R
)
pl <- pl %>%
config(
modeBarButtonsToAdd = list(plotly_copy_button),
displaylogo = FALSE,
toImageButtonOptions= list(format = "png", width = NULL, height = NULL)
)
pl
}
# based on https://stackoverflow.com/questions/64721568/how-can-i-create-a-custom-js-function-to-copy-plotly-image-to-clipboard-in-r-shi
# stackoverlow used Plotly.Snapshot.toImage, but need to use Plotly.toImage to control height width: https://github.com/plotly/plotly.js/issues/83
# see https://github.com/plotly/plotly.js/blob/master/src/plot_api/to_image.js for optional arguments
# this JS function needs to be added to ui.R
copy_plot_js <- 'function copyPlot(gd) {
var toImageButtonOptions = gd._context.toImageButtonOptions;
var opts = {
format: toImageButtonOptions.format || "png",
width: toImageButtonOptions.width || null,
height: toImageButtonOptions.height || null
};
Plotly.toImage(gd, opts).then(async function(url) {
try {
const data = await fetch(url);
const blob = await data.blob();
await navigator.clipboard.write([
new ClipboardItem({
[blob.type]: blob
})
]);
console.log("Image copied.");
} catch (err) {
console.error(err.name, err.message);
}
});
alert("Copied the plot");
}'