Представить данные geoJSON на карте Leaflet в Angular - PullRequest
0 голосов
/ 14 октября 2019

Я пытаюсь представить некоторые данные geoJSON на листовой карте. Файл geoJSON большой (60 МБ), а производительность сайта при загрузке данных ужасна. В geoJSON речь идет о плотности трафика и более, поэтому он содержит около 230 тыс. Сегментов ...

До сих пор я пытался реализовать leaflet.vectorgrid в угловом виде, создав leaflet.vectorgrid.d.ts, как упоминалось здесь . Это файл:

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 всегда работаетбыть таким большим (60 МБ) ... Итак, мне было интересно, есть ли способ отфильтровать данные, которые выбираются в пределах текущей ограничительной рамки.

Примечание файл хранитсяпока что локально, но позже я получу его из API.

1 Ответ

1 голос
/ 31 октября 2019

Следующий подход должен работать изначально с листовкой (без использования другой библиотеки):

this.map.getBounds() - возвращает LatLngBounds - границы (координаты 4 углов) карты - «ограничивающий»box "- это вы уже делаете.

LatLngBounds имеет метод с именем contains(), который возвращает true, если значение coords находится внутри ограничивающего прямоугольника: 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 функций. Если позволяет пользовательский опыт, вы также можете показать пользователю сообщение с просьбой увеличить или панорамировать до тех пор, пока число функций не станет ниже допустимого значения.

Примечание. Содержит () принимает LatLng и LatLngBounds. Чтобы увидеть, перекрывается ли полилиния или многоугольник или «содержится» в ограничительной рамке, либо:

Очевидно, что эти два метода будут давать разные результаты: центроид / перекрытие должно возвращать больше совпадений.

...