angular 模块构建_使用传单在Angular中构建地图,第4部分:形状服务

莫宝
2023-12-01

angular 模块构建

By now, we’ve built a Leaflet map in Angular and we are able to render markers and pop-ups. Let’s now render shapes for the different US states.

到目前为止 ,我们已经在Angular中构建了Leaflet地图 ,并且能够渲染标记和弹出窗口。 现在让我们为美国不同州渲染形状。

For this exercise, I downloaded a GeoJSON file that contains shape outlines of each state. Eric Celeste has an awesome site chock full of map data. I grabbed a 5m-GeoJSON states-outline from his site for this demo. Put this in your /assets/data folder.

在本练习中,我下载了一个GeoJSON文件,其中包含每个状态的形状轮廓。 Eric Celeste的站点真棒,塞满了地图数据。 我从他的站点抓取了一个5m-GeoJSON的状态概述进行演示 。 将其放在您的/assets/data文件夹中。

Note: If your local ng serve is already running, you’ll need to shut it down and restart in order to reload the new assets.

注意:如果您的本地服务器已经在运行,则需要将其关闭并重新启动以重新加载新资产。

建立 (Setup)

Our directory structure should look like this:

我们的目录结构应如下所示:

leaflet-example
|_ node_modules/
|_ package.json
\_ src/
    \_ app/
        |_ app.module.ts
        |_ app.routing.ts
        |_ app.component.ts
        |_ app.component.html
        |_ app.component.scss
        |
        |_ map/
        |     |_ map.component.ts
        |     |_ map.component.html
        |     \_ map.component.scss
        |
        \_ _services/
              |_ marker.service.ts
              |_ pop-up.service.ts

Let’s create another service that will be responsible for loading our shapes.

让我们创建另一个服务来负责加载形状。

$ ng generate service shape

Add this new service as a provider in your app.module.ts.

将此新服务添加为您的app.module.ts的提供者。

app.module.ts
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { MapComponent } from './map/map.component';
import { MarkerService } from './_services/marker.service';
import { HttpClientModule } from '@angular/common/http';
import { PopUpService } from './_services/pop-up.service';
import { ShapeService } from './_services/shape.service';@NgModule({
  declarations: [
    AppComponent,
    MapComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
  ],
  providers: [
    MarkerService,
    PopUpService,
    ShapeService
  ],
  bootstrap: [AppComponent]
})
export class AppModule {} 

加载形状 (Loading the Shapes)

In the ShapeService, we’ll only add a single function for now that will load the geojson file from our assets.

ShapeService ,我们现在仅添加一个函数,该函数将从资产中加载geojson文件。

shape.service.ts
shape.service.ts
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';@Injectable({
  providedIn: 'root'
})
export class ShapeService {

  constructor(private http: HttpClient) { }

  getStateShapes(): Observable<any> {
  return this.http.get('/assets/data/usa-states.geojson');
}
}

Our function getStateShapes() will return an observable of our serialized geojson object. To use this, we need to subscribe to the observable in our MapComponent. Here’s how:

我们的函数getStateShapes()将返回可观察到的序列化geojson对象。 要使用它,我们需要在MapComponent订阅observable。 这是如何做:

  1. Inject the ShapeService in the constructor.

    将ShapeService注入构造函数中。
  2. Create a local variable to house the data.

    创建一个局部变量来容纳数据。
  3. Call the shape service function to pull the data and subscribe to the result.

    调用形状服务函数以提取数据并订阅结果。
map.component.ts
map.component.ts
export class MapComponent implements AfterViewInit {

  private states;

  constructor(private markerService: MarkerService,
              private shapeService: ShapeService) { }

  ngAfterViewInit(): void {
    this.initMap();
    this.markerService.makeCapitalCircleMarkers(this.map);
    this.shapeService.getStateShapes().subscribe(states => {
  this.states = states;
});
  }

    // ... The rest of the class

}

Note: An even better approach would be to pre-load the data in a resolver.

注意:一种更好的方法是将数据预加载到解析器中。

Once the data are loaded, we’ll need to add the shapes to the map as a layer. Leaflet provides a factory just for geojson layers that we can leverage. Let’s stick this logic in its own function and then call it after the data has been resolved.

加载数据后,我们需要将形状作为图层添加到地图中。 Leaflet为我们可以利用的geojson图层提供了一个工厂。 让我们将此逻辑放在其自己的函数中,然后在数据解析后调用它。

map.component.ts
map.component.ts
// ...

  ngAfterViewInit(): void {
    this.initMap();
    this.markerService.makeCapitalCircleMarkers(this.map);
    this.shapeService.getStateShapes().subscribe(states => {
      this.states = states;
      this.initStatesLayer();
    });
  }

  private initStatesLayer() {
    const stateLayer = L.geoJSON(this.states, {
      style: (feature) => ({
        weight: 3,
        opacity: 0.5,
        color: '#008f68',
        fillOpacity: 0.8,
        fillColor: '#6DB65B'
      })
    });

    this.map.addLayer(stateLayer);
  }

  // ...

I created a new function, initStatesLayer(), that creates a new geojson layer and adds it to the map. I’ve also thrown in some basic styling. Refresh your browser.

我创建了一个新函数initStatesLayer() ,该函数创建了一个新的geojson图层并将其添加到地图中。 我还介绍了一些基本样式。 刷新浏览器。

Ta-da! We can now see the states - but we can also add a bit of code to interact with them.

- 现在我们可以看到状态-但我们也可以添加一些代码来与它们进行交互。

For this example, I’m going to have the feature highlight yellow when I hover my cursor over it, and reset back when I leave.

在此示例中,将光标悬停在该功能上时将其突出显示为黄色,离开时将其重置为黄色。

To do this, first define what to do on each feature using the appropriately-named onEachFeature property:

为此,首先使用适当命名的onEachFeature属性定义对每个功能执行的操作:

map.component.ts
map.component.ts
private initStatesLayer() {
    const stateLayer = L.geoJSON(this.states, {
      style: (feature) => ({
        weight: 3,
        opacity: 0.5,
        color: '#008f68',
        fillOpacity: 0.8,
        fillColor: '#6DB65B'
      }),
      onEachFeature: (feature, layer) => (
  layer.on({
    mouseover: (e) => (this.highlightFeature(e)),
    mouseout: (e) => (this.resetFeature(e)),
  })
)
    });

    this.map.addLayer(stateLayer);
  }

  private highlightFeature(e)  {
    const layer = e.target;
    layer.setStyle({
      weight: 10,
      opacity: 1.0,
      color: '#DFA612',
      fillOpacity: 1.0,
      fillColor: '#FAE042',
    });
  }

  private resetFeature(e)  {
    const layer = e.target;
    layer.setStyle({
      weight: 3,
      opacity: 0.5,
      color: '#008f68',
      fillOpacity: 0.8,
      fillColor: '#6DB65B'
    });
  }

Reload your browser and hover your cursor across the map:

重新加载浏览器并将光标悬停在地图上:

Hold on… where did our markers go? They’re still there, we’re just rendering the states on top of them because objects in the map are rendered in the order that they’re called. Because we create the markers first and then the shapes, the shapes win.

等等...我们的标记在哪里? 它们仍然存在,我们只是在它们之上渲染状态,因为地图中的对象是按照调用它们的顺序来渲染的。 因为我们先创建标记,然后再创建形状,所以形状获胜。

We can fix this in one of two ways:

我们可以通过以下两种方法之一来解决此问题:

  1. Move the marker call after the shape creation.

    创建形状后移动标记调用。
  2. Calling stateLayer.bringToBack() on the shape layer after we add it to the map.

    将形状图层添加到地图后,在形状图层上调用stateLayer.bringToBack()

In either case, we can now see the markers:

无论哪种情况,我们现在都可以看到标记:

Looks good!

看起来挺好的!

Happy Mapping

快乐映射

其他资源 (Additional Resources)

翻译自: https://www.digitalocean.com/community/tutorials/angular-angular-and-leaflet-shape-service

angular 模块构建

 类似资料: