はじめに
こんにちは。アーティサン株式会社の木戸です。
Angular で Google Maps を利用しランドマークなど大量のマーカーを表示した時、画面が煩雑になり見づらくなってしまう場合があるかと思います。
本記事ではそのような状況を回避するため、マーカーをクラスタリング(統合)して表示する、マーカークラスタリングライブラリを Angular に導入・設定する方法をご紹介します。
また、本番環境へ導入する際の注意点等もご紹介します。
Angular で 大量のマーカー表示によるユーザーエクスペリエンスの低下を改善したい方に向けた記事となります。
利用例
下の2枚の画像を見比べてください。1枚目の画像を見るとマーカーが多く、見づらくなっていますが、
マーカークラスタリングライブラリを利用すると、2枚目の画像のようにマーカーを統合して表示する事ができ、ユーザーエクスペリエンスを改善する事ができます。
Google Maps マーカークラスタリングライブラリ
(js-markerclustererplus)とは
表示されている Google Maps を一定のサイズの正方形で区切り、各正方形内に含まれているマーカーを統合し、1 つのクラスターマーカーで表示するライブラリです。
マーカーを統合して表示する事によって、ユーザーエクスペリエンスを改善する事ができます。
また、大量のマーカーを一度に扱わずにすむため、処理負荷を軽減する事もできます。
環境
- Node: 14.17.0
- npm: 6.14.13
- Angular: 12.1.1
- @angular/google-maps: 12.1.1
- @googlemaps/markerclustererplus: 1.2.0
- TypeScript: 4.3.5
導入
まず最初に、ライブラリと必要なファイル群を導入していきます。
インストール
@angular/google-maps のインストール
Angular で Google Maps を表示するためのライブラリをインストールします。
npm install @angular/google-maps
js-markerclustererplus のインストール
マーカークラスタリングライブラリをインストールします。
npm install @googlemaps/markerclustererplus
js-markerclustererplus インストール時の注意点
js-markerclustererplusにて 型定義 @types/google.maps のインストールが記載されていますが、@angular/google-maps 側ですでに型定義されているため、インストールの必要はありません。
(二重定義になってしまいます)
クラスタマーカー画像の用意
クラスターマーカーの画像は任意に設定可能であり、ライブラリ側で用意されている物または、独自に作成した物を使用できます。
ライブラリ側で用意されている画像を使用する場合
js-markerclustererplus/imagesにある画像をダウンロードし、Angular プロジェクトに組み込みます。
パスは適宜設定して下さい。
本番運用時の注意点
MapMarkerClustererの Loading the Library にて、script タグを使用しunpkg.com
から読み込んでいます。
しかしunpkg.com
が障害等で利用できない場合を考慮し、Angular プロジェクトのビルド時にライブラリを組み込むようにします。
ライブラリを組み込む形にすると、外部サーバーの障害を考慮する必要がなく、可用性を確保できるため本番運用に適しています。
Angular ビルド時に マーカークラスタリングライブラリ を取り込む
公開ライブラリの使用を参考に、下記設定を angular.json に記載し、ライブラリを Angular ビルドに組み込みます。
# angular.json
"scripts": ["node_modules/@googlemaps/markerclustererplus/dist/index.min.js"],
実装
シンプルな実装例を記載します。
実装方法
- Angular コンポーネントを作成
- HTML ファイルに google-map タグを追加
- google-map タグ内に map-marker-clusterer タグを追加
- map-marker-clusterer タグ内に、表示する map-marker タグを追加
Angular コンポーネントの作成
$ npx ng generate component sample
HTML ファイルに各種タグを追加
- コンポーネントのメンバ変数に、表示するマーカー位置の配列を設定します。(sample.component.ts: 10 行)
- 各種タグを追加し、*ngFor を用いてマーカー位置の配列からマーカーを生成します。(sample.component.html: 4 行)
// sample.component.ts
import { Component } from "@angular/core";
@Component({
selector: "app-sample",
templateUrl: "./sample.component.html",
styleUrls: ["./sample.component.scss"],
})
export class SampleComponent {
public markerPositions: google.maps.LatLngLiteral[] = [];
}
<!-- sample.component.html -->
<google-map>
<map-marker-clusterer imagePath="assets/images/m">
<ng-container *ngFor="let position of markerPositions">
<map-marker [position]="position"></map-marker>
</ng-container>
</map-marker-clusterer>
</google-map>
設定
パラメータ
主要なパラメータをご紹介します。
実装例
<map-marker-clusterer
[gridSize]="100"
[minimumclusterSize]="5"
[imageExtension]="'jpg'"
[imagePath]="'assets/images/m'"
[maxZoom]="12"
[zomOnclick]="false"
>
<!-- マーカーを追加 -->
</map-marker-clusterer>
gridSize(デフォルト値: 60)
クラスタリング処理を行う際に、表示されている Google Maps を区切る正方形のサイズ(ピクセル単位)を指定します。
値が大きい場合、より広い領域を 1 つのクラスターマーカーで表示します。
minimumClusterSize(デフォルト値: 2)
上記 gridSize で区切った 1 つの正方形内のマーカーの数が、この数以上になるとクラスターマーカーを表示します。
大きな数値にした場合、クラスタリングの効果が発揮されず、そのままマーカーが表示されるためあまり大きな数値を設定するのは推奨しません。
imageExtension(デフォルト値: ‘png’)
クラスターアイコンに使用する画像ファイルの拡張子。
imagePath(デフォルト値: ‘../images/m’)
クラスターアイコンに使用する画像ファイル名のプレフィックス。
実際に使用される画像ファイル名は以下の形で決定されます。
- imagePath + n + ‘.’ + imageExtension(n は 1,2 等、数字は 1 つのクラスターに含まれるマーカーの数によって変化します。)
maxZoom(デフォルト値: null)
クラスタリング処理を行う最大のズームレベル。
null の場合は全てのズームレベルでクラスタリング処理が行われます。
zoomOnClick(デフォルト値: true)
クラスターマーカーがクリックされた時に、マップをズームするかどうかを指定します。
イベント
クリックされた際などに発行されるイベントをご紹介します。
実装例
<map-marker-clusterer
(clusteringbegin)="sample1()"
(clusteringend)="sample2()"
(clusterClick)="sample3()"
>
<!-- マーカーを追加します -->
</map-marker-clusterer>
clusteringbegin
マーカーのクラスタリング処理の開始時にイベントが発行されます。
clusteringend
マーカーのクラスタリング処理の終了時にイベントが発行されます。
clusterClick
クラスターマーカーのクリック時にイベントが発行されます。
あとがき
本記事では導入、設定など基本的な部分をご紹介しました。
次回の記事では、クラスターマーカーの表示切り替え、マーカーアニメーション使用時の注意点等、より実践的な部分をご紹介致します。
関連リンク
木戸裕貴
私は主にTypeScriptでのフロントエンド開発を担当しております。