用R语言从一系列Leaflet地图中创建gif

12

我正在寻找一种自动化方法将 R Studio 中的 leaflet 绘图转换为图像文件。

似乎将 leaflet 小部件导出为 HTML 很简单(Saving leaflet output as html)。然而,我找不到任何关于如何将 leaflet 小部件生成的图像保存为图像的答案或文档。在 R Studio 中我可以手动完成此操作,但是没有一些可以调用以执行相同操作的 R Studio 函数,这很奇怪。

我已经尝试了以下常见的嫌疑人变体:

png("test_png.png")
map
dev.off()

但这些只是打印白色或打印一个甚至无法打开的文件。如果我正确理解了Git讨论,似乎leaflet中某些内容不可用但是用户需要。

同时,R Studio显然有一种方法将此图像渲染为图像文件,使我按下按钮即可完成。 有没有自动化的方法?我如何将在R Studio中绘制的图像导出为图像文件?我需要图像文件,并且我需要使其编程,因为我想从几百张地图制作一个gif

或者,我欢迎解决方法的建议。我可能会尝试这个:Python - 将HTML内容渲染为GIF图像,但如果有人有其他建议,请分享。


在类似的情况下,我所做的是创建所有地图并将它们保存为HTML文件。然后创建另一个HTML文件,其中仅包含一个iframe,用于读取您的地图文件。您需要学习一些JavaScript,但是您可以创建一个循环,通过iframe循环遍历您的HTML文件以制作GIF动画。不确定这是否适用于您的情况,但想提供给您参考。 - tblznbits
1
@brittenb 我以前实际上使用过那个解决方案,而且它可能适合我现在想要做的事情。好处是我不必局限于一个gif,可以随意混搭。顺便说一下,我喜欢你的个人资料;P - sunny
3个回答

14
我一直试图使用webshot包和htmltools中的saveWidget,虽然速度很慢。对于几百张地图来说,如果你只是偶尔需要使用,这可能还不错。但是,对于实时应用程序来说,它太慢了。
为此工作流程需要两个外部应用程序。 webshot用于网页截图,需要您先安装PhantomJS(它很小且易于安装)。我还使用ImageMagick(需要从命令行访问)创建.gif文件,但我相信有许多其他程序可以用来制作gif。
这个想法就是在循环中创建地图,用saveWidget将其保存到临时html文件中,并使用webshot将其转换为png(速度较慢)。然后,一旦您拥有所有的png文件,使用ImageMagick将它们转换为gif(速度快)。
以下是一个示例,我也加载了ggmap,但只是为了获取缩放位置。
library(webshot)
library(leaflet)
library(htmlwidgets)
library(ggmap)

loc <- geocode('mt everest')  # zoom in everest
zooms <- seq(2,14,3)          # some zoom levels to animate

## Make the maps, this will make some pngs called 'Rplot%02d.png'
## in your current directory
for (i in seq_along(zooms)) {
    m <- leaflet(data=loc) %>%
      addProviderTiles('Esri.WorldImagery') %>%
      setView(lng=loc$lon, lat=loc$lat, zoom=zooms[i])
    if (i==1)
        m <- m %>% addPopups(popup="Going to see Mt Everest")
    if (i==length(zooms))
       m <- m %>%
          addCircleMarkers(radius=90, opacity = 0.5) %>%
          addPopups(popup = 'Mt Everest')

    ## This is the png creation part
    saveWidget(m, 'temp.html', selfcontained = FALSE)
    webshot('temp.html', file=sprintf('Rplot%02d.png', i),
            cliprect = 'viewport')
}

然后,只需要将png转换为gif。我在Windows上完成了此操作,因此在mac / linux上命令可能略有不同(我认为只需单引号而不是双引号之类的)。这些命令来自命令行/ shell,但您也可以使用system/system2从R中调用,或尝试具有一些ImageMagick包装器函数的animation包。要制作一个简单的gif,只需使用convert *.png animation.gif即可。我使用了稍微长一些的代码来缩小png文件/添加一些延迟/并使序列进入和退出。

convert Rplot%02d.png[1-5] -duplicate 1,-2-1, -resize "%50" gif:- | convert - -set delay "%[fx:(t==0||t==4)?240:40]" -quiet -layers OptimizePlus -loop 0 cycle.gif

enter image description here


优秀的回答 - 好技巧。 - Mark Setchell
哇,非常感谢。我从你详细的回复中学到了很多东西。 - sunny

2

您可以按照jenesaisquoi的回答(第一个答案)创建一系列PNG文件。然后使用magick软件包中的以下代码,将png文件创建成gif文件。

library(magick)

    png.files <- sprintf("Rplot%02d.png", 1:20) #Mention the number of files to read
GIF.convert <- function(x, output = "animation.gif")#Create a function to read, animate and convert the files to gif
        {
        image_read(x) %>%
        image_animate(fps = 1) %>%
        image_write(output)
        }

        GIF.convert(png.files)

您不需要在电脑上安装ImageMagick软件。

代码链接:Animation.R


1
我有一个包含3列(纬度、经度和日期)的表格,共计376天。
流程如下:创建地图 -> 将地图保存为HTML -> 将地图保存为PNG -> 导入图片 -> 用plot + ggimage绘制。
所有这些过程都将在循环中进行。
library(leaflet)
library(animation)
library(png)
library(htmlwidgets)
library(webshot)
library(ggmap)

saveGIF({
for (i in 1:376) {
  map  = leaflet() %>%
    addTiles() %>%
    setView(lng = lon_lat[1,2], lat = lon_lat[1,1], zoom = 5)%>%
    addMarkers(lng = lon_lat[lon_lat$day == i,2],lat = lon_lat[lon_lat$day == i,1])

  saveWidget(map, 'temp.html', selfcontained = FALSE) ## save the html
  webshot('temp.html', file=sprintf('Rplot%02d.png', 1),cliprect = 'viewport') ## save as png
  img = readPNG("Rplot01.png") ### read the png
  plot(ggimage(img)) ###reading png file
}
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接