【问题标题】:Saving a Tmap plot in shiny以闪亮的方式保存 Tmap 图
【发布时间】:2020-10-31 07:38:15
【问题描述】:

我想添加一个功能,供用户在 Shiny 中导出地图,由 Tmap 制作。我知道 tmap 将地图转换为传单,但它不适用于 mapview::mapshot,因为许多答案都给出了在 Shiny 中保存 Leaflet 地图的答案。

以下都不起作用:

map_expr <- reactive({
    tm_shape(water1) +
      tm_fill(col = "darkblue") +
    tm_shape(county_outlines) +
      tm_borders(col = "black") +
    tm_shape(herd_summary) +
      tm_symbols(col = "green", size = "REACTORS", scale = 0.15, alpha = 0.7) +
    tm_shape(water1) +
      tm_fill(col = "darkblue")
  })
  
  observe({
    output$map <- renderTmap({
      map_expr()
    })
  })

output$downloadData <- downloadHandler(
    filename = "test.png",
    content = function(file) {
      # mapshot(map_expr(), file = file, cliprect = "viewport")
      # tmap_save(map_expr(), file = file)
      tmapProxy("map", session, {}) %>%
        mapview::mapshot(file = file)
    }
  )

【问题讨论】:

  • 我也遇到了同样的问题 - 您找到解决方案了吗?
  • 很遗憾没有;我最终做的是使用 renderPlot 和 plotOutput,它们使用静态图(如果熟悉 tmap,则为 tmap_mode("plot")),然后在下载处理程序中使用 tmap_save。这意味着绘图是非交互式的,但在我的例子中,用户能够保存地图比拥有交互式功能更重要。
  • 再看一遍后,我想我已经成功了,我会添加它作为答案

标签: r leaflet maps tmap


【解决方案1】:

经过反复试验,我最终让它工作,并在此处包含了一个可重现的示例,如下所示:

library(shiny)
library(tmap)
library(mapview)

data("World")
pal <- leaflet::colorBin(palette = grDevices::heat.colors(20), domain = World$HPI)

ui <- fluidPage(

    titlePanel("Tmap Example"),

    sidebarLayout(
        sidebarPanel(
            downloadButton("downloadData")
        ),
        mainPanel(
            tmapOutput("map")
        )
    )
)

server <- function(input, output) {
    map_expr <- reactive({
        tm_shape(World) +
            tm_polygons("HPI")
    })
    
    output$map <- renderTmap({
        map_expr()
    })
    
    output$downloadData <- downloadHandler(
        filename = "test.png",
        content = function(file) {
            mapview::mapshot(tmap_leaflet(map_expr()), file = file)
        }
    )
}

shinyApp(ui = ui, server = server)

因此必须将 tmap 表达式保存到一个对象中(我将它保存到一个名为 map_expr 的反应式对象中,因此在代码中的其他位置调用此对象时必须包含括号)。

使用mapview包中的mapshot函数,可以保存一个leaflet对象,tmap中有一个叫做tamp_leaflet的函数,可以将tmap对象转换为leaflet对象。

首先在应用程序之外对其进行测试,以确保 mapshot 可以正常工作。为了让它工作,我必须安装包 webshot 并且必须安装 phantomJS,这可以通过以下函数完成: webshot::install_phantomjs()

希望这会有所帮助!

【讨论】:

  • 非常感谢。由于我的工作的安全权限,我不能使用 webshot::install_phantomjs() 但我可以看到它会起作用。但和你一样,我的用户对静态图像更感兴趣,所以你上面的评论(关于 renderPlot)就像一种享受!
  • 您也可以上传您的原始代码吗?我真的很好奇你是如何设法将调色板添加到 tmap 中的 - 我不断收到各种错误,例如: tmap_HMTC_map
  • 如果没有您的数据和代码,我无法重现您的错误,但函数 tm_polygons 的“pal”参数将接受十六进制字符向量,因此以下行有效:pal = c(" #DC0032","#FFF5AC","#00B0F0")
  • 函数 colorRampPalette 返回一个调色板函数,而不是一个字符向量;我将添加我的代码作为另一个答案,以便更容易阅读
【解决方案2】:
library(tmap)
data("World")

# pal accepts a character vector of colours
tm_shape(World) +
  tm_polygons("HPI", pal = c("#DC0032","#FFF5AC","#00B0F0"))

# You can also store the palette in pal, 
# and then call pal(3) to return three colours
pal = grDevices::colorRampPalette(c("#DC0032","#FFF5AC","#00B0F0"))
tm_shape(World) +
  tm_polygons("HPI", pal = pal(3))

【讨论】:

    猜你喜欢
    • 2019-10-22
    • 2021-06-14
    • 2015-10-22
    • 2018-10-03
    • 2018-07-19
    • 2018-11-23
    • 2021-02-08
    • 2019-07-25
    • 2019-09-25
    相关资源
    最近更新 更多