Ответ 1
Вот предложение. Стратегия такова:
- пусть зритель построит
png
- отправьте
png
от зрителя до R
Пусть зритель построит png
Изображение canvas
имеет метод .toDataURL()
который возвращает URI данных, содержащий представление изображения в формате png
(мы также можем получить формат jpeg
).
Библиотека html2canvas
может быть использована для снятия скриншота: эта библиотека отображает текущую страницу как изображение в canvas
.
Таким образом, можно комбинировать эти две функции в средстве просмотра:
- сделать скриншот с
html2canvas
- преобразуйте этот снимок экрана в
png
используя.toDataURL()
Однако в библиотеке html2canvas
используется JavaScript Promise
, которые не поддерживаются программой просмотра RStudio (Windows version): требуется полипол.
Отправьте png
от зрителя до R
Эта задача может быть достигнута с помощью WebSockets.
Пакет httpuv
можно использовать для создания веб-сервера. Этот сервер будет обслуживать HTML
страницу, которая будет открыта в средстве просмотра RStudio
.
Связь WebSocket устанавливается между сервером httpuv
и средством просмотра RStudio.
Из командной строки 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) {
wsUrl = paste(sep='',
'"',
"ws://",
ifelse(is.null(req$HTTP_HOST), req$SERVER_NAME, req$HTTP_HOST),
'"')
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:
sprintf("var ws = new WebSocket(%s);", wsUrl),
# 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)