假设我在查看器窗格中查看了以下HTML
tempDir <- tempfile()
dir.create(tempDir)
htmlFile <- file.path(tempDir, "index.html")
write('<h1> Content</h1>', htmlFile, append = TRUE)
write('<h2> Content</h2>', htmlFile, append = TRUE)
write('lorem ipsum...', htmlFile, append = TRUE)
viewer <- getOption("viewer")
viewer(htmlFile)
当我在查看器窗格中拥有此html时,我可以单击“另存为图像”按钮:
我将html内容作为png,例如:
是否可以通过命令行执行此操作?我了解rstudioapi::savePlotAsImage()
,因此我正在寻找一种saveViewerAsImage
。
编辑:我知道我们可以使用{webshot}包来做到这一点,但是我正在寻找能够做到这一点的RStudio函数。
答案 0 :(得分:10)
这是个提案。该策略如下:
png
png
发送到R png
canvas
image拥有一个.toDataURL()
method,它返回一个数据URI,其中包含png
格式的图像表示形式(我们也可以得到jpeg
格式)。
html2canvas
library可用于截屏:此库将当前页面呈现为canvas
图像。
因此,可以在查看器中结合这两个功能:
html2canvas
png
将屏幕截图转换为.toDataURL()
但是,html2canvas
库使用(Windows版本)RStudio查看器不支持的JavaScript Promise
:需要polyfill。
png
发送到R 可以使用WebSockets完成此任务。
httpuv
软件包可用于创建Web服务器。该服务器将提供一个HTML
页面,该页面将在RStudio
查看器中打开。
httpuv
服务器与RStudio查看器之间建立了WebSocket通信。
从R命令行,可以将WebSocket消息发送到RStudio查看器:接收到此消息后,查看器获取屏幕截图并将其发送回服务器。
对不起,此代码对于一个SO答案来说很长。
library(httpuv)
# Initialize variables
png <- NULL
websocket <- NULL
# Download Javascript libraries
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')
# Configure the httpuv server
app <- list(
call = function(req) {
list(
status = 200L,
headers = list(
'Content-Type' = 'text/html'
),
body = paste0(collapse = "\r\n",
c("<!DOCTYPE html>",
"<html>",
"<head>",
# polyfill the RStudio viewer to support JavaScript promises
'<script type="text/javascript">',
polyfill_promise,
"</script>",
# use html2canvas library
'<script type="text/javascript">',
html2canvas,
"</script>",
"</head>",
"<body>",
html_body,
"</body>",
'<script type="text/javascript">',
# Configure the client-side websocket connection:
'var ws = new WebSocket("ws://" + location.host);',
# When a websocket message is received:
"ws.onmessage = function(event) {",
# Take a screenshot of the HTML body element
" html2canvas(document.body).then(function(canvas) {",
# Transform it to png
" var dataURL = canvas.toDataURL();",
# Send it back to the server
" ws.send(dataURL);",
" });",
"};",
"</script>",
"</html>"
)
)
)
},
# Configure the server-side websocket connection
onWSOpen = function(ws) {
# because we need to send websocket message from the R command line:
websocket <<- ws
# when a websocket message is received from the client
ws$onMessage(function(binary, message) {
png <<- message
})
}
)
# From your question:
html_body <- c(
'<h1> Content</h1>',
'<h2> Content</h2>',
'lorem ipsum...'
)
# Start the server:
server <- startDaemonizedServer("0.0.0.0", 9454, app)
# Open the RStudio viewer:
rstudioapi::viewer("http://localhost:9454")
# Wait to see the result...
# Send a websocket message from the command line:
websocket$send("go") # send any message
# Write the png image to disk:
writeBin(
RCurl::base64Decode(
gsub("data:image/png;base64,", "", png),
"raw"
),
"screenshot.png"
)
# Close the websocket connection
websocket$close()
# Stop the server
stopDaemonizedServer(server)