这是一个提议。策略如下:
1.让观看者构建
png
。
2.将
png
从观看者发送到R。
让观看者构建
png
canvas
图像具有一个
.toDataURL()
方法,返回一个包含以
png
格式表示的图像的数据URI(我们也可以得到
jpeg
格式)。
可以使用
html2canvas
库来截屏:该库将当前页面呈现为
canvas
图像。
因此,可以在观看者中结合这两个功能:
1.使用
html2canvas
进行截屏。
2.使用
.toDataURL()
将此截屏转换为
png
。
然而,
html2canvas
库使用
Promise
,这在(Windows版本)RStudio查看器中不受支持:需要使用
polyfill。
将查看器中的png
发送到R
可以使用WebSockets来完成此任务。
可以使用httpuv
包创建Web服务器。该服务器将提供一个HTML
页面,该页面将在RStudio
查看器中打开。
在httpuv
服务器和RStudio查看器之间建立WebSocket通信。
从R命令行可以向RStudio查看器发送WebSocket消息:接收此消息后,查看器会拍摄屏幕截图并将其发送回服务器。
代码
很抱歉,此代码对于SO答案来说相当长。
library(httpuv)
png <- NULL
websocket <- NULL
polyfill_promise <- readLines('https://cdn.jsdelivr.net/npm/es6-promise/dist/es6-promise.auto.min.js')
html2canvas <- readLines('https://html2canvas.hertzen.com/dist/html2canvas.min.js')
app <- list(
call = function(req) {
list(
status = 200L,
headers = list(
'Content-Type' = 'text/html'
),
body = paste0(collapse = "\r\n",
c("<!DOCTYPE html>",
"<html>",
"<head>",
'<script type="text/javascript">',
polyfill_promise,
"</script>",
'<script type="text/javascript">',
html2canvas,
"</script>",
"</head>",
"<body>",
html_body,
"</body>",
'<script type="text/javascript">',
'var ws = new WebSocket("ws://" + location.host);',
"ws.onmessage = function(event) {",
" html2canvas(document.body).then(function(canvas) {",
" var dataURL = canvas.toDataURL();",
" ws.send(dataURL);",
" });",
"};",
"</script>",
"</html>"
)
)
)
},
onWSOpen = function(ws) {
websocket <<- ws
ws$onMessage(function(binary, message) {
png <<- message
})
}
)
html_body <- c(
'<h1> Content</h1>',
'<h2> Content</h2>',
'lorem ipsum...'
)
server <- startDaemonizedServer("0.0.0.0", 9454, app)
rstudioapi::viewer("http://localhost:9454")
websocket$send("go")
writeBin(
RCurl::base64Decode(
gsub("data:image/png;base64,", "", png),
"raw"
),
"screenshot.png"
)
websocket$close()
stopDaemonizedServer(server)
wsUrl
可以改为location.host
? - Yihui Xie