【问题标题】:How to capture html output as png in R如何在R中将html输出捕获为png
【发布时间】:2023-12-26 02:21:01
【问题描述】:

我使用 R 中 networkD3 包创建的交互式输出。我知道如何将输出保存为 html 页面,但我还需要将图表的“静态”版本保存为 .png 文件。

代码如下:

# Load package
library(networkD3)

# Create fake data
src <- c("A", "A", "A", "A", "B", "B", "C", "C", "D")
target <- c("B", "C", "D", "J", "E", "F", "G", "H", "I")
networkData <- data.frame(src, target)

# Plot
simpleNetwork(networkData)

我可以通过单击“导出”然后单击“另存为图像”来保存输出。不过,我更喜欢在我的代码中使用一些命令来保存图片。

【问题讨论】:

  • 这是在完整的网络浏览器中还是在 RStudio 的窗口中?因为如果它是一个网络浏览器,那么RSelenium 包将为您完成...
  • 它在 RStudio 查看器窗口中。我也想最终从 Jupyter Notebook 运行它。
  • 您可能会发现此讨论很有帮助。 github.com/ramnathv/htmlwidgets/issues/95
  • @JeanV.Adams 我找到了这个function 谢谢你。我能够自定义它,所以它完全符合我的需要。再次感谢您!
  • @LenkaVraná 有没有机会为我们这些不太熟悉 PhantomJS 的人写下它作为答案?

标签: r png htmlwidgets networkd3


【解决方案1】:

我使用了这个页面上的函数https://github.com/hafen/trelliscope/blob/master/R/thumb.R 并试图简化它。

您需要从http://phantomjs.org/download.html 安装 PhantomJS,并在环境变量中设置路径。

函数如下所示(参数p 是html 小部件,thumbName 是新的.png 文件的名称):

library(htmlwidgets)

widgetThumbnail <- function(p, thumbName, width = 1024, height = 768) {
  phantom <- findPhantom()

  success <- FALSE
  if(phantom == "") {
    message("** phantomjs dependency could not be found - thumbnail cannot be generated (run phantomInstall() for details)")
  } else {
    res <- try({
      ff <- paste0(thumbName, ".html")
      ffjs <- paste0(thumbName, ".js")

      # don't want any padding
      p$sizingPolicy$padding <- 0
      suppressMessages(saveWidget(p, ff, selfcontained = FALSE))

      js <- paste0("var page = require('webpage').create();
                    page.viewportSize = { width: ", width,", height: ", height," };
                    page.clipRect = { top: 0, left: 0, width: ", width,", height: ", height," };
                    page.open('", ff, "', function(status) {
                    console.log(\"Status: \" + status);
                    if(status === \"success\") {
                    page.render('", thumbName, ".png');
                    }
                    phantom.exit();
                    });")
      cat(js, file = ffjs)
      system2(phantom, ffjs)
    })
    if(!inherits(res, "try-error")) {
      success <- TRUE
    }
    if(!file.exists(paste0(thumbName, ".png"))) {
      success <- FALSE
    }
  }

  if(!success) {
    message("** could not create htmlwidget thumbnail... creating an empty thumbnail...")
  }
}

#' Get instructions on how to install phantomjs
#' @export
phantomInstall <- function() {
  message("Please visit this page to install phantomjs on your system: http://phantomjs.org/download.html")
}

# similar to webshot
findPhantom <- function() {

  phantom <- Sys.which("phantomjs")

  if(Sys.which("phantomjs") == "") {
    if(identical(.Platform$OS.type, "windows")) {
      phantom <- Sys.which(file.path(Sys.getenv("APPDATA"), "npm", "phantomjs.cmd"))
    }
  }

  phantom

}

它创建 .js 文件,该文件获取您的 html 小部件,捕获屏幕并将 .js、.html 和 .png 文件保存到活动目录中:

# Load package
library(networkD3)

# Create fake data
src <- c("A", "A", "A", "A", "B", "B", "C", "C", "D")
target <- c("B", "C", "D", "J", "E", "F", "G", "H", "I")
networkData <- data.frame(src, target)

# Plot
plot = simpleNetwork(networkData)

# Save html as png
widgetThumbnail(p = plot, thumbName = "plot", height = 500)

【讨论】:

    【解决方案2】:

    只是对可能解决方案的更新。有一个名为 webshot 的包(由 W. Chang 等人编写),它执行此渲染并截取 html 页面的屏幕截图。

    例如用法:

    webshot::webshot("file.html")
    

    要获取 html 文件,您可能需要查看 R. Vaidyanathan 等人的 htmlwidgets::saveWidget


    一个完全可重现的示例(将 simpleNetwork.png 保存在您当前的工作目录中)

    library(networkD3)
    
    src <- c("A", "A", "A", "A", "B", "B", "C", "C", "D")
    target <- c("B", "C", "D", "J", "E", "F", "G", "H", "I")
    networkData <- data.frame(src, target)
    
    sn <- simpleNetwork(networkData)
    saveNetwork(sn, "sn.html")
    
    library(webshot)
    webshot("sn.html", "simpleNetwork.png")
    

    【讨论】: