如何创建包含数千个不会使浏览器崩溃的标记的传单地图?

时间:2022-10-31 22:52:11

I'm using the leaflet package in R to generate a map with a large number of circles on it. The goal is a map I can publish to my website. The problem I'm having is that as I increase the number of circles, the resulting map loads very slowly, I get "unresponsive script" warnings and ultimately it completely freezes up my browser.

我正在使用R中的传单包来生成一个包含大量圆圈的地图。目标是我可以发布到我的网站的地图。我遇到的问题是,当我增加圈数时,生成的地图加载速度非常慢,我得到“无响应的脚本”警告,最终它完全冻结了我的浏览器。

I know this sort of thing is possible, because I've found a leaflet map that works the way I want mine to work:

我知道这种事情是可能的,因为我发现了一张传单,可以按我希望的方式工作:

http://cartologic.com/geoapps/map_viewer/5/ny-crimes-2014-dot-density-map

I notice on the above map that the circles don't appear "clickable" like the circles on my map, and that they seem to load in square chunks. I have a hunch that these things are related to my problem. Unfortunately, I'm too much of a novice at leaflet/javascript stuff to figure this out on my own.

我在上面的地图上注意到,圆圈看起来并不像我在地图上的圆圈那样“可点击”,而且它们看起来像方块一样加载。我预感到这些事情与我的问题有关。不幸的是,我在传单/ javascript的东西上太多了,不能自己解决这个问题。

Here is a toy example illustrating my problem:

这是一个说明我的问题的玩具示例:

library("leaflet")
library("htmlwidgets")

dots <- data.frame(x=c(runif(10000, -93.701281, -93.533053)),
                   y=c(runif(10000,  41.515962,  41.644369)))

m <- leaflet(dots) %>%
  addTiles('http://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png') %>% 
  setView(-93.617167, 41.580166, zoom = 12) %>% 
  addCircles(~x, ~y, weight = 1, radius = 5, 
             color = "#FFA500", stroke = TRUE, fillOpacity = 0.1) 

m

saveWidget(widget = m, file="example.html", selfcontained = TRUE)

4 个解决方案

#1


3  

mapview can help you here. It builds upon the leaflet library for smaller data sets, but uses special javascript functionality for larger data.

mapview可以帮到你。它建立在小叶库的基础上,用于较小的数据集,但对较大的数据使用特殊的javascript功能。

your example with 1 Mio. points:

你的例子是1 Mio.要点:

library(mapview)
library(sp)

dots <- data.frame(x=c(runif(1000000, -93.701281, -93.533053)),
                   y=c(runif(1000000,  41.515962,  41.644369)))

coordinates(dots) <- ~ x + y
proj4string(dots) <- "+init=epsg:4326"

mapview(dots)

It may still take a while to render, but once rendered it should be quite responsive. Note that mapview is designed to work with spatial* objects, that is why we need the calls to set the coordinate slot and the projection.

渲染可能还需要一段时间,但一旦渲染它应该是非常敏感的。请注意,mapview旨在使用spatial *对象,这就是我们需要调用来设置坐标槽和投影的原因。

For more information have a look here:

有关详细信息,请查看此处:

http://environmentalinformatics-marburg.github.io/web-presentations/20150723_mapView.html

Hope that helps.

希望有所帮助。

#2


1  

If you want to add a large number of vector objects to a map, it is rare that it can be done easily.

如果要向地图添加大量矢量对象,很少能够轻松完成。

Notice that the raster data is broken into tiles so that all the information does not have to be shown at one time. For your vector data (in this case, circles) you have to do the same thing.

请注意,栅格数据被分解为瓦片,因此不必一次显示所有信息。对于矢量数据(在本例中为圆圈),您必须执行相同的操作。

Basically what I like to do is to break the large data set into smaller (vector) tiles, with the same boundaries as the raster tiles you are showing. Duplicate the data if you want it to appear at several zoom level. As you are showing circle, imagine that you partition the circles' center points on the tile boundary.

基本上我喜欢做的是将大数据集分成更小的(矢量)图块,边界与您显示的栅格图块相同。如果希望数据以多个缩放级别显示,请复制数据。当您显示圆圈时,假设您在圆弧边界上划分圆的中心点。

I have an application similar to this where I basically partition my vector data on tile boundaries and store the information in geojson files. When I get an event that the raster tile has been loaded I can then load the equivalent vector file as a geojson layer (same thing when the raster tile is unloaded). In this way, you can limit the amount of vector data that has to be displayed at any one time.

我有一个类似于此的应用程序,我基本上将我的矢量数据分区在tile边界上,并将信息存储在geojson文件中。当我得到一个已加载栅格图块的事件时,我可以将等效矢量文件加载为geojson图层(当光栅图块被卸载时也是如此)。通过这种方式,您可以限制任何时候必须显示的矢量数据量。

If you have a lot of points, they are not really going to be visible at low zoom levels anyway, so it might be better just to show them at an appropriate zoom level (perhaps with a different representation at low zooms - like a heat map). This will keep the amount of data being shown at any one time lower.

如果你有很多分数,那么无论如何它们都不会在低变焦水平下显示,所以最好只是以适当的缩放级别显示它们(可能在低变焦时使用不同的表示 - 比如热图)。这将使任何时候显示的数据量保持较低。

#3


1  

Since this question has a few upvotes, I'll generally describe both of the solutions I found. Maybe if I have time later I'll get all the files together on GitHub.

由于这个问题有几个赞成,我通常会描述我找到的两个解决方案。也许如果我以后有时间,我会在GitHub上将所有文件放在一起。

First, I found TileMill. Simply load a data file of coordinates into TileMill, style the way you want them to appear, and output tiles (png). Host those tiles on the web somewhere and load them with leaflet. This process was a bit too manual for my liking because TileMill kept crashing when I loaded in csv files that were too large for it to render on my machine.

首先,我找到了TileMill。只需将坐标数据文件加载到TileMill中,按照您希望的方式显示样式,然后输出切片(png)。在某个地方托管这些瓷砖并用传单加载它们。这个过程对我来说有点过于谨慎,因为当我加载csv文件时,TileMill会一直崩溃,因为csv文件太大而无法在我的机器上渲染。

I found the best solution was use Processing, adapting Robert Manduca's code here: https://github.com/rmanduca/jobmaps. I don't use Python so I rewrote those parts in R and modified the Processing code according to my specifications.

我发现最好的解决方案是使用Processing,在这里调整Robert Manduca的代码:https://github.com/rmanduca/jobmaps。我不使用Python,所以我在R中重写了这些部分,并根据我的规范修改了处理代码。

#4


1  

Mapdeck (released on CRAN Aug 2018) uses WebGL (through Deck.gl) and is designed to handle millions of points (depending on your system's hardware of course)

Mapdeck(于2018年8月在CRAN上发布)使用WebGL(通过Deck.gl),旨在处理数百万个点(当然,取决于系统的硬件)

library(mapdeck)

set_token("MAPBOX_TOKEN")

n <- 1e6
dots <- data.frame(x=c(runif(n, -93.701281, -93.533053)),
                   y=c(runif(n,  41.515962,  41.644369)))


dots$letter <- sample(letters, size = n, replace = T)

mapdeck(
    style = mapdeck_style('dark')
) %>%
    add_scatterplot(
        data = dots
        , lon = "x"
        , lat = "y"
        , fill_colour = "letter"
        , radius = 5
        , fill_opacity = 50
        , layer_id = "dots"
    )

如何创建包含数千个不会使浏览器崩溃的标记的传单地图?

#1


3  

mapview can help you here. It builds upon the leaflet library for smaller data sets, but uses special javascript functionality for larger data.

mapview可以帮到你。它建立在小叶库的基础上,用于较小的数据集,但对较大的数据使用特殊的javascript功能。

your example with 1 Mio. points:

你的例子是1 Mio.要点:

library(mapview)
library(sp)

dots <- data.frame(x=c(runif(1000000, -93.701281, -93.533053)),
                   y=c(runif(1000000,  41.515962,  41.644369)))

coordinates(dots) <- ~ x + y
proj4string(dots) <- "+init=epsg:4326"

mapview(dots)

It may still take a while to render, but once rendered it should be quite responsive. Note that mapview is designed to work with spatial* objects, that is why we need the calls to set the coordinate slot and the projection.

渲染可能还需要一段时间,但一旦渲染它应该是非常敏感的。请注意,mapview旨在使用spatial *对象,这就是我们需要调用来设置坐标槽和投影的原因。

For more information have a look here:

有关详细信息,请查看此处:

http://environmentalinformatics-marburg.github.io/web-presentations/20150723_mapView.html

Hope that helps.

希望有所帮助。

#2


1  

If you want to add a large number of vector objects to a map, it is rare that it can be done easily.

如果要向地图添加大量矢量对象,很少能够轻松完成。

Notice that the raster data is broken into tiles so that all the information does not have to be shown at one time. For your vector data (in this case, circles) you have to do the same thing.

请注意,栅格数据被分解为瓦片,因此不必一次显示所有信息。对于矢量数据(在本例中为圆圈),您必须执行相同的操作。

Basically what I like to do is to break the large data set into smaller (vector) tiles, with the same boundaries as the raster tiles you are showing. Duplicate the data if you want it to appear at several zoom level. As you are showing circle, imagine that you partition the circles' center points on the tile boundary.

基本上我喜欢做的是将大数据集分成更小的(矢量)图块,边界与您显示的栅格图块相同。如果希望数据以多个缩放级别显示,请复制数据。当您显示圆圈时,假设您在圆弧边界上划分圆的中心点。

I have an application similar to this where I basically partition my vector data on tile boundaries and store the information in geojson files. When I get an event that the raster tile has been loaded I can then load the equivalent vector file as a geojson layer (same thing when the raster tile is unloaded). In this way, you can limit the amount of vector data that has to be displayed at any one time.

我有一个类似于此的应用程序,我基本上将我的矢量数据分区在tile边界上,并将信息存储在geojson文件中。当我得到一个已加载栅格图块的事件时,我可以将等效矢量文件加载为geojson图层(当光栅图块被卸载时也是如此)。通过这种方式,您可以限制任何时候必须显示的矢量数据量。

If you have a lot of points, they are not really going to be visible at low zoom levels anyway, so it might be better just to show them at an appropriate zoom level (perhaps with a different representation at low zooms - like a heat map). This will keep the amount of data being shown at any one time lower.

如果你有很多分数,那么无论如何它们都不会在低变焦水平下显示,所以最好只是以适当的缩放级别显示它们(可能在低变焦时使用不同的表示 - 比如热图)。这将使任何时候显示的数据量保持较低。

#3


1  

Since this question has a few upvotes, I'll generally describe both of the solutions I found. Maybe if I have time later I'll get all the files together on GitHub.

由于这个问题有几个赞成,我通常会描述我找到的两个解决方案。也许如果我以后有时间,我会在GitHub上将所有文件放在一起。

First, I found TileMill. Simply load a data file of coordinates into TileMill, style the way you want them to appear, and output tiles (png). Host those tiles on the web somewhere and load them with leaflet. This process was a bit too manual for my liking because TileMill kept crashing when I loaded in csv files that were too large for it to render on my machine.

首先,我找到了TileMill。只需将坐标数据文件加载到TileMill中,按照您希望的方式显示样式,然后输出切片(png)。在某个地方托管这些瓷砖并用传单加载它们。这个过程对我来说有点过于谨慎,因为当我加载csv文件时,TileMill会一直崩溃,因为csv文件太大而无法在我的机器上渲染。

I found the best solution was use Processing, adapting Robert Manduca's code here: https://github.com/rmanduca/jobmaps. I don't use Python so I rewrote those parts in R and modified the Processing code according to my specifications.

我发现最好的解决方案是使用Processing,在这里调整Robert Manduca的代码:https://github.com/rmanduca/jobmaps。我不使用Python,所以我在R中重写了这些部分,并根据我的规范修改了处理代码。

#4


1  

Mapdeck (released on CRAN Aug 2018) uses WebGL (through Deck.gl) and is designed to handle millions of points (depending on your system's hardware of course)

Mapdeck(于2018年8月在CRAN上发布)使用WebGL(通过Deck.gl),旨在处理数百万个点(当然,取决于系统的硬件)

library(mapdeck)

set_token("MAPBOX_TOKEN")

n <- 1e6
dots <- data.frame(x=c(runif(n, -93.701281, -93.533053)),
                   y=c(runif(n,  41.515962,  41.644369)))


dots$letter <- sample(letters, size = n, replace = T)

mapdeck(
    style = mapdeck_style('dark')
) %>%
    add_scatterplot(
        data = dots
        , lon = "x"
        , lat = "y"
        , fill_colour = "letter"
        , radius = 5
        , fill_opacity = 50
        , layer_id = "dots"
    )

如何创建包含数千个不会使浏览器崩溃的标记的传单地图?