无法使用R的leaflet包循环生成多个地图

11

我是新手,也比较新于R语言,因此请原谅我的初学者问题。我想创建一个叶片地图序列(从1971年9月到1972年4月)。最终,我希望将它们压缩成闪亮的动画,并让用户播放/暂停动画(闪亮循环动画滑块)。使用while和for循环对我没有用。当我运行代码后检查我的i时,增量已经工作,但是leaflet函数没有工作。在没有循环的情况下,“Dynamic Leaflet Fails”(请参见下面的代码部分)有效并打开一张地图。不可能按顺序创建叶片吗?

#set working directory
require(leaflet)
require(dplyr)

#Build data.frame with 10 obs + 3 cols
power <- data.frame(Latitude <-c(33.515556, 38.060556, 47.903056, 49.71, 49.041667, 31.934167, 54.140586, 54.140586, 48.494444, 48.494444), Longitude <- c(
129.837222, -77.789444, 7.563056, 8.415278, 9.175, -82.343889, 13.664422, 13.664422, 17.681944, 17.681944), start <- c(as.Date(
"15-Sep-1971", "1-Dec-1971", "1-Feb-1972", "1-Feb-1972", "1-Feb-1972", "1-Feb-1972", "1-Apr-1972", "1-Apr-1972", "24-Apr-1972", "24-Apr-1972", format = "%d-%b-%Y")))

#"Dynamic" leaflet Fails1: While+For combo
i<- as.Date("1971-09-14")
while (i < as.Date("1972-05-01")) {    for(star in start){
if (star > i) {
leaflet(power) %>% addTiles() %>%
  addCircleMarkers(lng = ~Longitude, lat = ~Latitude)
}}
i <- i+60}

#"Dynamic" leaflet Fails2: For+break combo
lap <- seq(as.Date("1971-09-14"), as.Date("1972-05-01"), by = "month")
for(i in lap) {
leaflet (data = power[power$start > i,]) %>%
addTiles() %>%
addCircleMarkers(lng = ~Longitude, lat = ~Latitude)  
if (i > as.Date("1951-01-01")) 
{      break }}

谢谢alistaire!(感谢你!) 动态和静态leaflet地图有什么区别?如果有的话,我可能错过了一些重要信息。(请指教!) 我认为,leaflet不会让shiny干扰到调整,但是我可能错了,欢迎提供建议。(请多多指教!) 在所有这些东西中,我正在尝试创建像这样的东西:(https://seth127.shinyapps.io/slider/),但我找不到任何以前的项目中结合shiny循环动画和leaflet的代码。 如果您有建议,请告诉我!(请多指教!) - Naibaf
哎呀!研究工作的投入度降到了-3。回到本科时,我的心都碎了。说真的,我进行了很多试错和上网搜索,可能比我的帖子所涉及的还要多。请与我分享你们的想法。 - Naibaf
这是一张包含所有我的坐标点要绘制的单一leaflet地图:(http://homepage.univie.ac.at/a1009991/power.html)逐个绘制标记实在讲述了一个惊人的故事, 伙计们,将它实现真是太棒了!有什么建议吗?我想创建类似于这个的东西:(http://skeate.github.io/Leaflet.timeline/earthquakes.html) - Naibaf
“Dynamic” 意味着它构建的是 HTML 地图,而不是 JPG 或 PNG 格式的地图。如果想要动画效果,一个简单的选项是使用 ggplot2+ggmaps+gganimate。如果你真的很懒,可以把整个东西放在 CartoDB 上;如果不那么懒,可使用 它的 R 包。使用 Leaflet 可以通过其 add*remove* 函数实现,但您将需要添加时间轴,可能需要一些工作来完成。 - alistaire
1
我不同意-3,也不知道有谁已经展示了解决方案,所以我很快会尝试回答。 - timelyportfolio
显示剩余2条评论
2个回答

16

这是一个快速的方法来按照你建议的方式添加leaflet-timeline。由于某些原因,时间轴在RStudio Viewer中不能完美地呈现,但在Chrome中似乎可以正常工作。我在代码中内联注释以描述步骤。

library(htmlwidgets)
library(htmltools)
library(leaflet)
library(geojsonio)

#Build data.frame with 10 obs + 3 cols
power <- data.frame(
  "Latitude" = c(33.515556, 38.060556, 47.903056, 49.71, 49.041667, 31.934167, 54.140586, 54.140586, 48.494444, 48.494444),
  "Longitude" = c(129.837222, -77.789444, 7.563056, 8.415278, 9.175, -82.343889, 13.664422, 13.664422, 17.681944, 17.681944),
  "start" = do.call(
    "as.Date",
    list(
      x = c("15-Sep-1971", "1-Dec-1971", "1-Feb-1972", "1-Feb-1972", "1-Feb-1972", "1-Feb-1972", "1-Apr-1972", "1-Apr-1972", "24-Apr-1972", "24-Apr-1972"),
      format = "%d-%b-%Y"
    )
  )
)

# set start same as end
#  adjust however you would like
power$end <- power$start


# use geojsonio to convert our data.frame
#  to GeoJSON which timeline expects
power_geo <- geojson_json(power,lat="Latitude",lon="Longitude")

# create a leaflet map on which we will build
leaf <- leaflet() %>%
  addTiles()

# add leaflet-timeline as a dependency
#  to get the js and css
leaf$dependencies[[length(leaf$dependencies)+1]] <- htmlDependency(
  name = "leaflet-timeline",
  version = "1.0.0",
  src = c("href" = "http://skeate.github.io/Leaflet.timeline/"),
  script = "javascripts/leaflet.timeline.js",
  stylesheet = "stylesheets/leaflet.timeline.css"
)

# use the new onRender in htmlwidgets to run
#  this code once our leaflet map is rendered
#  I did not spend time perfecting the leaflet-timeline
#  options
leaf %>%
  setView(44.0665,23.74667,2) %>%
  onRender(sprintf(
    '
function(el,x){
    var power_data = %s;

    var timeline = L.timeline(power_data, {
      pointToLayer: function(data, latlng){
        var hue_min = 120;
        var hue_max = 0;
        var hue = hue_min;
        return L.circleMarker(latlng, {
          radius: 10,
          color: "hsl("+hue+", 100%%, 50%%)",
          fillColor: "hsl("+hue+", 100%%, 50%%)"
        });
      },
      steps: 1000,
      duration: 10000,
      showTicks: true
    });
    timeline.addTo(HTMLWidgets.find(".leaflet"));
}
    ',
    power_geo
))

1
timelyportfolio,您是一个真正的巫师和绅士。我选择了power$end <- power$start + 90来实际看到标记,并且我会进一步尝试。非常感谢您。 - Naibaf
@timelyportfolio。非常好的回答。如果要根据变量设置颜色条件,您会怎么做? - MLavoie
如果我理解正确的话,您可以在sprintf中使用jsonlite::toJSON添加一个颜色映射。因此,var colors = %s,然后jsonlite::toJSON(list(var1 = list(color = "...", fillColor="...", ...), auto_unbox = TRUE),最后在JavaScript中添加查找。很难在评论中解释清楚。 - timelyportfolio
我已经构建了一个叶轮时间轴包[leaftime](https://github.com/timelyportfolio/leaftime),以使这一过程更加容易。 - timelyportfolio

13

这是去年@timelyportfolio发布的帖子的更新版本。我需要添加timelineControl函数才能使其正常工作。我还需要调用leaflet元素的getMap()函数,以使函数绑定到地图对象。

library(htmlwidgets)
library(htmltools)
library(leaflet)
library(geojsonio)

#Build data.frame with 10 obs + 3 cols
power <- data.frame(
    "Latitude" = c(33.515556, 38.060556, 47.903056, 49.71, 49.041667, 31.934167, 54.140586, 54.140586, 48.494444, 48.494444),
    "Longitude" = c(129.837222, -77.789444, 7.563056, 8.415278, 9.175, -82.343889, 13.664422, 13.664422, 17.681944, 17.681944),
    "start" = do.call(
        "as.Date",
        list(
            x = c("15-Sep-1971", "1-Dec-1971", "1-Feb-1972", "1-Feb-1972", "1-Feb-1972", "1-Feb-1972", "1-Apr-1972", "1-Apr-1972", "24-Apr-1972", "24-Apr-1972"),
            format = "%d-%b-%Y"
        )
    )
)

# set start same as end
#  adjust however you would like
power$end <- power$start + 30


# use geojsonio to convert our data.frame
#  to GeoJSON which timeline expects
power_geo <- geojson_json(power,lat="Latitude",lon="Longitude", pretty = T)

# create a leaflet map on which we will build
leaf <- leaflet() %>%
    addTiles()

# add leaflet-timeline as a dependency
#  to get the js and css
leaf$dependencies[[length(leaf$dependencies)+1]] <- htmlDependency(
    name = "leaflet-timeline",
    version = "1.0.0",
    src = c("href" = "http://skeate.github.io/Leaflet.timeline/"),
    script = "javascripts/leaflet.timeline.js",
    stylesheet = "stylesheets/leaflet.timeline.css"
)

# use the new onRender in htmlwidgets to run
#  this code once our leaflet map is rendered
#  I did not spend time perfecting the leaflet-timeline
#  options
leaf %>%
    setView(44.0665,23.74667,2) %>%
    onRender(sprintf(
        '
        function(el,x){
        var power_data = %s;

        var timelineControl = L.timelineSliderControl({
          formatOutput: function(date) {
            return new Date(date).toString();
          }
        });

        var timeline = L.timeline(power_data, {
        pointToLayer: function(data, latlng){
        var hue_min = 120;
        var hue_max = 0;
        var hue = hue_min;
        return L.circleMarker(latlng, {
        radius: 10,
        color: "hsl("+hue+", 100%%, 50%%)",
        fillColor: "hsl("+hue+", 100%%, 50%%)"
        });
        },
        steps: 1000,
        duration: 10000,
        showTicks: true
        });
        timelineControl.addTo(HTMLWidgets.find(".leaflet").getMap());
        timelineControl.addTimelines(timeline);
        timeline.addTo(HTMLWidgets.find(".leaflet").getMap());
        }
        ',
        power_geo
    ))

@timelyportfolio:这很好,但是如果您有一个更复杂的数据框架,如何指示哪个变量保存时间线信息?在 geojson_json() 中是否有相应的参数? - Amy M

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