从R中的一系列Leaflet地图创建一个gif

时间:2015-11-03 20:30:08

标签: r leaflet rstudio

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

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

我已经尝试过常见的嫌疑人,以下内容的变体:

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

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

与此同时,R Studio显然有办法将这个图像渲染成图像文件,让我按一个按钮来完成它。 有没有办法实现自动化?如何将在R Studio中绘制的图像导出到图像文件?我需要图像文件,我需要这是程序化的,因为我想从几百张地图中制作gif

或者,我欢迎有关解决方法的建议。我可能会尝试这样做:Python - render HTML content to GIF image但如果有人提出替代建议,请分享。

3 个答案:

答案 0 :(得分:12)

我一直尝试使用saveWidget包和来自htmltools的{​​{1}}的组合来做到这一点,尽管它很慢。对于几百张地图,如果你只是在这里和那里做它可能不是太糟糕。但是,对于实时应用来说,它太慢了。

此工作流程需要两个外部应用程序。 webshot会截取网页截图,并要求您先安装PhantomJS(这很简单)。我还使用webshot(并且需要可以从命令行访问)来创建.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包。要制作一个没有花哨的simle 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

ImageMagick

答案 1 :(得分:2)

您可以创建一系列PNG文件,由jenesaisquoi(第一个答案)回答。然后使用下面的代码用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)

您无需在PC上安装ImageMagick软件。

代码链接:Animation.R

答案 2 :(得分:0)

我有3列的表:lat,lon,day(376天)。

过程是:创建地图 - &gt;将地图另存为HTML - &gt;将地图另存为PNG - &gt;导入图片 - &gt;绘制它(用情节+ 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
}
})