リーフレットを使用してAngularでマップを作成する方法、パート2:マーカーサービス
序章
リーフレットはマーカーをサポートします。 これらは、情報を含むことができるマップ上に配置されたインジケーターです。 これは、地図上のランドマークと目的地を強調表示する方法を提供します。
注:これは、AngularとLeafletの使用に関する4部構成のシリーズのパート2です。
このチュートリアルでは、サービスを使用してマーカーロジックを管理することにより、マップにマーカーを追加する方法を学習します。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- このチュートリアルは、前のパーツのインストールと手順に直接基づいています。
ステップ1—GeoJSONデータをダウンロードする
このチュートリアルでは、アメリカ合衆国の州都のGeoJSONデータをプロットします。 また、州名、首都名、人口に関する追加のメタデータも含まれます。
注: usa-capitals.geojsonファイルは、付属のプロジェクトリポジトリで入手できます。
新しいを作成します data
下のサブディレクトリ assets
ディレクトリ:
- mkdir src/assets/data
次に、を保存します usa-capitals.geojson
このディレクトリ内のファイル。
ステップ2—マーカーサービスの作成
この時点で、AngularアプリケーションにLeafletの実装が機能しているはずです。
ターミナルウィンドウを使用して、プロジェクトディレクトリに移動します。 次に、次のコマンドを実行して、新しいサービスを生成します。
- npx @angular/cli generate service marker --skip-tests
これにより、新しいファイルが作成されます。 marker.service.ts
.
次に、この新しいサービスをプロバイダーとして追加します app.module.ts
. また、からデータをロードします assets
フォルダを含める必要があります HttpClientModule
.
開ける 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 { AppComponent } from './app.component';
import { MapComponent } from './map/map.component';
@NgModule({
declarations: [
AppComponent,
MapComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [
MarkerService
],
bootstrap: [AppComponent]
})
export class AppModule { }
これで、アプリケーションが新しいアプリケーションをサポートします MarkerService
.
ステップ3—マーカーのロードとプロット
次に、新しく作成したものを開きます marker.service.ts
コードエディタで追加します HttpClient
コンストラクターへ:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class MarkerService {
capitals: string = '/assets/data/usa-capitals.geojson';
constructor(private http: HttpClient) { }
}
GeoJSONデータをロードし、マーカーを作成する新しい関数を作成します。 この関数は、リーフレットマップをパラメーターとして受け取ります。
変更 marker.service.ts
リーフレットをインポートして宣言するには makeCapitalMarkers
関数:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import * as L from 'leaflet';
@Injectable({
providedIn: 'root'
})
export class MarkerService {
capitals: string = '/assets/data/usa-capitals.geojson';
constructor(private http: HttpClient) { }
makeCapitalMarkers(map: L.map): void { }
}
使用する HttpClient
、データを取得し、 subscribe
結果に。
データを取得したら、各フィーチャをループしてマーカーを作成し、それをマップに追加します。
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import * as L from 'leaflet';
@Injectable({
providedIn: 'root'
})
export class MarkerService {
capitals: string = '/assets/data/usa-capitals.geojson';
constructor(private http: HttpClient) {
}
makeCapitalMarkers(map: L.map): void {
this.http.get(this.capitals).subscribe((res: any) => {
for (const c of res.features) {
const lon = c.geometry.coordinates[0];
const lat = c.geometry.coordinates[1];
const marker = L.marker([lat, lon]);
marker.addTo(map);
}
});
}
}
このコードは、マーカーをマップにロードおよび追加するためのロジックを処理します。
ここで、このメソッドをから呼び出す必要があります MapComponent
:
import { Component, AfterViewInit } from '@angular/core';
import * as L from 'leaflet';
import { MarkerService } from '../marker.service';
@Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.css']
})
export class MapComponent implements AfterViewInit {
private map;
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);
}
constructor(private markerService: MarkerService) { }
ngAfterViewInit(): void {
this.initMap();
this.markerService.makeCapitalMarkers(this.map);
}
}
この時点でアプリケーションを実行すると、コンソールで次の2つのエラーが発生します。
Outputmarker-icon-2x.png:1 GET http://localhost:4200/marker-icon-2x.png 404 (Not Found)
marker-shadow.png:1 GET http://localhost:4200/marker-shadow.png 404 (Not Found)
リーフレットのアセットをプロジェクトにインポートして、 marker-icon-2x.png
と marker-shadow.png
画像ファイル。
を開きます angular.json
ファイルを作成し、リーフレットを追加します images
ディレクトリ:
{
// ...
"projects": {
"angular-leaflet-example": {
// ...
"architect": {
"build": {
// ...
"options": {
// ...
"assets": [
"src/favicon.ico",
"src/assets",
{
"glob": "**/*",
"input": "node_modules/leaflet/dist/images/",
"output": "./assets"
}
],
// ..
},
// ...
},
// ...
}
}},
"defaultProject": "angular-leaflet-example"
}
このコードは、リーフレットのマーカー画像をローカルにコピーします。
次に、 map.component.ts
アイコンを定義します。
import { Component, AfterViewInit } from '@angular/core';
import * as L from 'leaflet';
import { MarkerService } from '../marker.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;
constructor(private markerService: MarkerService) { }
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);
}
ngAfterViewInit(): void {
this.initMap();
this.markerService.makeCapitalMarkers(this.map);
}
}
変更を保存します。 次に、アプリケーションを停止して再起動します。 Webブラウザでアプリケーションを開きます(localhost:4200
)そして州都のマーカーを観察します:
この時点で、デフォルトのマーカーをサポートするマップができました。
ステップ4—サークルマーカーの表示
この次のステップでは、マーカーをアイコンから円に変更します。 次に、州議会議事堂の人口を反映するように円のサイズをスケーリングします。
開ける MarkerService
を作成します makeCapitalCircleMarkers()
関数。 それは非常に似ています makrCapitalMarkers()
関数。 リーフレットのインスタッド marker
メソッド、あなたは使用します circleMarker
方法:
makeCapitalCircleMarkers(map: L.map): void {
this.http.get(this.capitals).subscribe((res: any) => {
for (const c of res.features) {
const lon = c.geometry.coordinates[0];
const lat = c.geometry.coordinates[1];
const circle = L.circleMarker([lat, lon]);
circle.addTo(map);
}
});
}
次に、この関数をで呼び出します MapComponent
:
ngAfterViewInit(): void {
this.initMap();
// this.markerService.makeCapitalMarkers(this.map);
this.markerService.makeCapitalCircleMarkers(this.map);
}
これらの変更を保存し、Webブラウザでアプリケーションを開きます(localhost:4200
):
アイコンが円に置き換えられました。
circleMarker
3番目のオプションのパラメーターを受け入れます。 このオブジェクトには、 radius
財産。 あなたの中で MarkerService
、変更します makeCapitalCircleMarkers
の半径を使用する関数 20
:
const circle = L.circleMarker([lat, lon], { radius: 20 }).addTo(map);
このコードは、すべての半径を同じ値になるようにサイズ設定します(20
).
次に、州都の人口を反映するように半径を変更します。
static scaledRadius(val: number, maxVal: number): number {
return 20 * (val / maxVal);
}
この関数は、値(母集団)、最大値(最大母集団)を受け取り、[0〜20]の範囲の半径を返します。
スプレッド演算子を使用し、 map
人口が最も多い首都を見つけるには:
const maxPop = Math.max(...res.features.map(x => x.properties.population), 0);
GeoJSONデータから、最大の人口は次のようになります:「アリゾナ州フェニックス」(1626078
).
最後に、を使用してすべてをまとめます ScaledRadius
半径関数として。
開ける MarkerService
コードエディタで、次の変更を加えます。
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import * as L from 'leaflet';
@Injectable({
providedIn: 'root'
})
export class MarkerService {
capitals: string = '/assets/data/usa-capitals.geojson';
constructor(private http: HttpClient) { }
static scaledRadius(val: number, maxVal: number): number {
return 20 * (val / maxVal);
}
makeCapitalMarkers(map: L.map): void {
this.http.get(this.capitals).subscribe((res: any) => {
for (const c of res.features) {
const lon = c.geometry.coordinates[0];
const lat = c.geometry.coordinates[1];
const marker = L.marker([lat, lon]);
marker.addTo(map);
}
});
}
makeCapitalCircleMarkers(map: L.map): void {
this.http.get(this.capitals).subscribe((res: any) => {
const maxPop = Math.max(...res.features.map(x => x.properties.population), 0);
for (const c of res.features) {
const lon = c.geometry.coordinates[0];
const lat = c.geometry.coordinates[1];
const circle = L.circleMarker([lat, lon], {
radius: MarkerService.scaledRadius(c.properties.population, maxPop)
});
circle.addTo(map);
}
});
}
}
変更を保存します。 次に、アプリケーションを停止して再起動します。 Webブラウザでアプリケーションを開きます(localhost:4200
)そして州都の新しいスケーリングされた円マーカーを観察します。
これで、マーカーをサポートするマップができました。
結論
この投稿では、データを読み込んでマーカーを作成するマーカーサービスを作成しました。 2種類のマーカーを作成する方法を学びました。 L.marker
と L.circleMarker
. 最後に、半径の関数を渡すことにより、各円マーカーのサイズを定義する方法を学びました。
AngularとLeafletの使用に関するこのシリーズのパート3に進みます。