リーフレットを使用してAngularでマップを作成する方法、パート4:シェイプサービス
序章
リーフレットは図形をサポートしています。 境界のデータを含むGeoJSONファイルを提供することにより、地図上に郡、州、国を示すことができます。
注:これは、AngularとLeafletの使用に関する4部構成のシリーズのパート4です。
このチュートリアルでは、アメリカ合衆国の大陸の州の形状をレンダリングする方法を学習します。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- このチュートリアルは、前のパーツのインストールと手順に直接基づいています。
ステップ1—GeoJSONデータをダウンロードする
このチュートリアルでは、アメリカ合衆国の州の概要についてGeoJSONデータをプロットします。
Eric Celesteの米国のGeoJSONおよびKMLデータにアクセスし、5mのGeoJSONファイルをダウンロードします(gz_2010_us_040_00_5m.json
).
このファイルを /assets/data
ディレクトリ。
ステップ2—シェイプサービスを作成する
この時点で、AngularアプリケーションにLeafletの実装が機能しているはずです。
ターミナルウィンドウを使用して、プロジェクトディレクトリに移動します。 次に、次のコマンドを実行して、新しいサービスを生成します。
- npx @angular/cli generate service shape --skip-tests
これにより、新しいファイルが作成されます。 shape.service.ts
.
次に、この新しいサービスをプロバイダーとして追加します app.module.ts
.
開ける app.module.ts
コードエディタで、次の変更を加えます。
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { MarkerService } from './marker.service';
import { PopupService } from './popup.service';
import { ShapeService } from './shape.service';
import { AppComponent } from './app.component';
import { MapComponent } from './map/map.component';
@NgModule({
declarations: [
AppComponent,
MapComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [
MarkerService,
PopupService,
ShapeService
],
bootstrap: [AppComponent]
})
export class AppModule { }
これで、アプリケーションが新しいアプリケーションをサポートします ShapeService
.
ステップ3—図形を読み込む
次に、新しく作成したものを開きます shape.service.ts
コードエディタで追加します HttpClient
コンストラクターへ:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class ShapeService {
constructor(private http: HttpClient) { }
getStateShapes() {
return this.http.get('/assets/data/gz_2010_us_040_00_5m.json');
}
}
関数 getStateShapes()
シリアル化されたGeoJSONオブジェクトのオブザーバブルを返します。 これを使用するには、でobservableをサブスクライブする必要があります MapComponent
.
import { Component, AfterViewInit } from '@angular/core';
import * as L from 'leaflet';
import { MarkerService } from '../marker.service';
import { ShapeService } from '../shape.service';
// ...
@Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.css']
})
export class MapComponent implements AfterViewInit {
private map;
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;
});
}
}
このコードは ShapeService
コンストラクターで、データを格納するローカル変数を作成し、 getStateShapes()
データをプルして結果をサブスクライブする関数。
注:さらに良いアプローチは、リゾルバーにデータをプリロードすることです。
データが読み込まれたら、図形をレイヤーとしてマップに追加する必要があります。 Leafletは、活用できるGeoJSONレイヤー専用のファクトリを提供します。 このロジックを独自の関数に入れて、データが解決された後に呼び出しましょう。
// ...
@Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.css']
})
export class MapComponent implements AfterViewInit {
private map;
private states;
// ...
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);
}
ngAfterViewInit(): void {
this.initMap();
this.markerService.makeCapitalCircleMarkers(this.map);
this.shapeService.getStateShapes().subscribe(states => {
this.states = states;
this.initStatesLayer();
});
}
}
The initStatesLayer()
関数は新しいGeoJSONレイヤーを作成し、それをマップに追加します。
変更を保存します。 次に、アプリケーションを停止して再起動します。 Webブラウザでアプリケーションを開きます(localhost:4200
)そして州の境界を観察します:
次に、添付します mouseover
と mouseout
各形状と相互作用するイベント onEachFeature
:
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'
});
}
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);
}
変更を保存します。 次に、Webブラウザでアプリケーションを開きます(localhost:4200
)そして、マウスを図形の上に移動します。
ただし、シェイプレイヤーがマーカーレイヤーの上にあるため、マーカーはかすかに見えます。
これに対処するには2つのアプローチがあります。 最初のアプローチは、 makeCapitalCircleMarkers()
直後に電話する initStatesLayer()
. 2番目のアプローチは bringToBack()
マップに追加された後のシェイプレイヤー上。
これが完全です map.component.ts
とファイル bringToBack()
アプローチ:
import { Component, AfterViewInit } from '@angular/core';
import * as L from 'leaflet';
import { MarkerService } from '../marker.service';
import { ShapeService } from '../shape.service';
const iconRetinaUrl = 'assets/marker-icon-2x.png';
const iconUrl = 'assets/marker-icon.png';
const shadowUrl = 'assets/marker-shadow.png';
const iconDefault = L.icon({
iconRetinaUrl,
iconUrl,
shadowUrl,
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
tooltipAnchor: [16, -28],
shadowSize: [41, 41]
});
L.Marker.prototype.options.icon = iconDefault;
@Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.css']
})
export class MapComponent implements AfterViewInit {
private map;
private states;
constructor(
private markerService: MarkerService,
private shapeService: ShapeService
) { }
private initMap(): void {
this.map = L.map('map', {
center: [ 39.8282, -98.5795 ],
zoom: 3
});
const tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
minZoom: 3,
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
});
tiles.addTo(this.map);
}
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'
});
}
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);
stateLayer.bringToBack();
}
ngAfterViewInit(): void {
this.initMap();
// this.markerService.makeCapitalMarkers(this.map);
this.markerService.makeCapitalCircleMarkers(this.map);
this.shapeService.getStateShapes().subscribe(states => {
this.states = states;
this.initStatesLayer();
});
}
}
変更を保存します。 次に、Webブラウザでアプリケーションを開きます(localhost:4200
)そして州都のスケーリングされた円マーカーと州境の形状を観察します。
これで、形状をサポートするマップができました。
結論
この投稿では、データを読み込んで図形を作成する図形サービスを作成しました。 との双方向性を追加しました L.GeoJSON
の onEachFeature()
と L.DomEvent.On
.
これで、AngularとLeafletの使用に関する4部構成のシリーズは終わりです。
Angularについて詳しく知りたい場合は、Angularトピックページで演習とプログラミングプロジェクトを確認してください。