在 Angular 中在 Leaflet 地图上显示 geoJSON 数据
Present geoJSON data on Leaflet map in Angular
我正在尝试在传单地图上显示一些 geoJSON 数据。 geoJSON 文件很大 (60mb),加载数据时站点的性能很差。 geoJSON 是关于交通密度等等,所以它包含大约 230k 段...
到目前为止,我尝试过的是通过创建here 中提到的leaflet.vectorgrid.d.ts
在angular 中实现leaflet.vectorgrid
。这是文件:
import * as L from "leaflet";
declare module "leaflet" {
namespace vectorGrid {
export function slicer(data: any, options?: any): any;
}
}
虽然表现还差
到目前为止,这是我的代码:
import { Component, OnInit } from "@angular/core";
import {
MapOptions,
LatLng,
TileLayer,
Map,
LeafletEvent,
Circle,
Polygon
} from "leaflet";
import * as L from "leaflet";
import { HttpClient } from "@angular/common/http";
@Component({
selector: "map-visualization",
templateUrl: "./map-visualization.component.html",
styleUrls: ["./map-visualization.component.scss"]
})
export class MapVisualizationComponent implements OnInit {
leafletOptions: MapOptions;
layersControl: any;
map: Map;
constructor(private http: HttpClient) {}
ngOnInit() {
this.initializeMap();
}
/**
* Initializes the map
*/
initializeMap() {
this.leafletOptions = {
layers: [
new TileLayer(
"https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}",
{
maxZoom: 18
}
)
],
zoom: 4,
center: new LatLng(48.1323827, 4.172899)
};
}
/**
* Once the map is ready, it pans to the user's current location and loads the map.geojson
* @param map Map instance
*/
onMapReady(map: Map) {
this.map = map;
if (navigator) {
navigator.geolocation.getCurrentPosition(position => {
this.map.setView(
new LatLng(position.coords.latitude, position.coords.longitude),
12
);
});
}
this.http.get("assets/map.json").subscribe((json: any) => {
L.geoJSON(json).addTo(this.map);
});
}
/**
* Return the current bound box
* @param event Leaflet event
*/
onMapMoveEnd(event: LeafletEvent) {
console.log("Current BBox", this.map.getBounds().toBBoxString());
}
}
最后,geoJSON 总是那么大 (60mb)...
所以,我想知道是否有一种方法可以过滤在当前边界框内获取的数据。
注意 该文件暂时存储在本地,但稍后我将从 API.
中获取它
以下方法应该可以在 leaflet 中原生使用(无需依赖其他库):
this.map.getBounds()
- returns LatLngBounds
- 地图的边界(4 个角的坐标) - "bounding box" - 这你已经在做。
LatLngBounds
有一个名为 contains()
的方法,如果 coords
的值在边界框内,则 returns true
:https://leafletjs.com/reference-1.5.0.html#latlngbounds-contains
您可以创建一个可以从 onMapReady()
和 onMapMoveEnd()
调用的方法,它会执行如下操作:
addItemsToMap(items: []): Layer[] {
const tempLayer: Layer[] = [];
items.forEach(item => {
if (item.coordinates) {
const itemCoordinates = latLng(
item.coordinates.latitude,
item.coordinates.longitude
);
/** Only add items to map if they are within map bounds */
if (this.map.getBounds().contains(itemCoordinates)) {
tempLayer.push(
marker(itemCoordinates, {
icon: icon(
this.markers['red']
),
title: item.description
})
);
}
}
});
return tempLayer;
}
根据我的经验,Leaflet 可以轻松处理多达 800 个特征。如果用户体验允许,您还可以向用户显示一条消息,要求他们缩放或平移,直到特征数量低于可容忍的数量。
注意:contains() 接受 LatLng
和 LatLngBounds
。要查看多段线或多边形是否重叠或 "is contained by" 边界框,可以:
- 使用质心并传递为
LatLng
。 polyline/polygon 有一个 getCenter()
方法:https://leafletjs.com/reference-1.5.0.html#polyline-getcenter
- "wrap" 将多段线放入方框内,如
LatLngBounds
所示。 polyline/polygon 有一个 getBounds()
方法:https://leafletjs.com/reference-1.5.0.html#polyline-getbounds
这两种方法显然会return不同的结果:centroid/overlap应该return更多的匹配。
我正在尝试在传单地图上显示一些 geoJSON 数据。 geoJSON 文件很大 (60mb),加载数据时站点的性能很差。 geoJSON 是关于交通密度等等,所以它包含大约 230k 段...
到目前为止,我尝试过的是通过创建here 中提到的leaflet.vectorgrid.d.ts
在angular 中实现leaflet.vectorgrid
。这是文件:
import * as L from "leaflet";
declare module "leaflet" {
namespace vectorGrid {
export function slicer(data: any, options?: any): any;
}
}
虽然表现还差
到目前为止,这是我的代码:
import { Component, OnInit } from "@angular/core";
import {
MapOptions,
LatLng,
TileLayer,
Map,
LeafletEvent,
Circle,
Polygon
} from "leaflet";
import * as L from "leaflet";
import { HttpClient } from "@angular/common/http";
@Component({
selector: "map-visualization",
templateUrl: "./map-visualization.component.html",
styleUrls: ["./map-visualization.component.scss"]
})
export class MapVisualizationComponent implements OnInit {
leafletOptions: MapOptions;
layersControl: any;
map: Map;
constructor(private http: HttpClient) {}
ngOnInit() {
this.initializeMap();
}
/**
* Initializes the map
*/
initializeMap() {
this.leafletOptions = {
layers: [
new TileLayer(
"https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}",
{
maxZoom: 18
}
)
],
zoom: 4,
center: new LatLng(48.1323827, 4.172899)
};
}
/**
* Once the map is ready, it pans to the user's current location and loads the map.geojson
* @param map Map instance
*/
onMapReady(map: Map) {
this.map = map;
if (navigator) {
navigator.geolocation.getCurrentPosition(position => {
this.map.setView(
new LatLng(position.coords.latitude, position.coords.longitude),
12
);
});
}
this.http.get("assets/map.json").subscribe((json: any) => {
L.geoJSON(json).addTo(this.map);
});
}
/**
* Return the current bound box
* @param event Leaflet event
*/
onMapMoveEnd(event: LeafletEvent) {
console.log("Current BBox", this.map.getBounds().toBBoxString());
}
}
最后,geoJSON 总是那么大 (60mb)... 所以,我想知道是否有一种方法可以过滤在当前边界框内获取的数据。
注意 该文件暂时存储在本地,但稍后我将从 API.
中获取它以下方法应该可以在 leaflet 中原生使用(无需依赖其他库):
this.map.getBounds()
- returns LatLngBounds
- 地图的边界(4 个角的坐标) - "bounding box" - 这你已经在做。
LatLngBounds
有一个名为 contains()
的方法,如果 coords
的值在边界框内,则 returns true
:https://leafletjs.com/reference-1.5.0.html#latlngbounds-contains
您可以创建一个可以从 onMapReady()
和 onMapMoveEnd()
调用的方法,它会执行如下操作:
addItemsToMap(items: []): Layer[] {
const tempLayer: Layer[] = [];
items.forEach(item => {
if (item.coordinates) {
const itemCoordinates = latLng(
item.coordinates.latitude,
item.coordinates.longitude
);
/** Only add items to map if they are within map bounds */
if (this.map.getBounds().contains(itemCoordinates)) {
tempLayer.push(
marker(itemCoordinates, {
icon: icon(
this.markers['red']
),
title: item.description
})
);
}
}
});
return tempLayer;
}
根据我的经验,Leaflet 可以轻松处理多达 800 个特征。如果用户体验允许,您还可以向用户显示一条消息,要求他们缩放或平移,直到特征数量低于可容忍的数量。
注意:contains() 接受 LatLng
和 LatLngBounds
。要查看多段线或多边形是否重叠或 "is contained by" 边界框,可以:
- 使用质心并传递为
LatLng
。 polyline/polygon 有一个getCenter()
方法:https://leafletjs.com/reference-1.5.0.html#polyline-getcenter - "wrap" 将多段线放入方框内,如
LatLngBounds
所示。 polyline/polygon 有一个getBounds()
方法:https://leafletjs.com/reference-1.5.0.html#polyline-getbounds
这两种方法显然会return不同的结果:centroid/overlap应该return更多的匹配。