技術情報ブログ
TypeScript
2021.10.27

AngularでGoogle Maps マーカークラスタリングライブラリの利用(2)

AngularでGoogle Maps マーカークラスタリングライブラリの利用(2)

こんにちは。アーティサン株式会社の木戸です。

前回に引き続き、Angular で Google Maps を利用した時の、大量のマーカー表示によるユーザーエクスペリエンスの低下を回避する方法についてご紹介します。

前編では、マーカークラスタリングライブラリの Angular への導入、設定方法等、基本的な部分に触れました。
本記事では、より実践的な内容としてクラスターマーカーの表示・非表示の切り替え、マーカーアニメーション使用時の注意点を記載致します。

Angular でマーカークラスタリングライブラリ(js-markerclustererplus)を利用し、クラスターマーカーの表示・非表示の切り替えを行いたい方に向けた記事となります。

 

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

 

クラスターマーカーの表示・非表示の切り替え

クラスターマーカーを表示しているコンポーネント自体に表示切り替えの設定がないため、下記の実装手順で切り替えを行います。
今回の例ではマップのクリックイベントにマーカーの表示切り替えを行う関数を設定する形で実装します。

 

実装手順

  • クラスターマーカーの ignoreHidden プロパティを true に設定
  • クラスターマーカー内にある、各マーカーコンポーネントの visible プロパティを更新
  • クラスターマーカーの repaint メソッドを呼び出す

 

クラスターマーカーに ignoreHidden を設定

ignoreHidden プロパティを true に設定します。(6 行目)

ignoreHidden とは

クラスターマーカー内にある、非表示のマーカーコンポーネント(visible プロパティが false)を無視するかどうかを設定します。
true に設定する事によって、visible プロパティが false のマーカーコンポーネントがクラスターマーカーに含まれなくなります。

<!-- sample.component.html -->
<google-map (mapClick)="toggleMarkers()">
  <map-marker-clusterer
    #markerClusterer="mapMarkerClusterer"
    imagePath="assets/images/m"
    [ignoreHidden]="true"
  >
    <ng-container *ngFor="let position of markerPositions">
      <map-marker [position]="position"></map-marker>
    </ng-container>
  </map-marker-clusterer>
</google-map>

 

クラスタマーカー内にある、各マーカーコンポーネントの visible を更新

typescript ファイル内で@ViewChild を使用し、html ファイルにある map-marker-cluster コンポーネントを取得します。(10 行目)

クラスターマーカー内にある各マーカーコンポーネントの visible プロパティを更新し、表示切り替えを行います。(15, 16 行目)

// sample.component.ts
import { Component } from "@angular/core";

@Component({
  selector: "app-sample",
  templateUrl: "./sample.component.html",
  styleUrls: ["./sample.component.scss"],
})
export class SampleComponent {
  @ViewChild("markerClusterer") markerClusterer!: MapMarkerClusterer;

  public markerPositions: google.maps.LatLngLiteral[] = [];

  public toggleMarkers(): void {
    const markers = this.markerClusterer?.markerClusterer?.getMarkers() ?? [];
    for (const marker of markers) marker.setVisible(!marker.getVisible());
    this.markerClusterer?.markerClusterer?.repaint();
  }
}

 

クラスターマーカーの repaint メソッドを呼び出す

各マーカーコンポーネントの visible プロパティ更新後、画面表示の更新をするため、repaint メソッドを呼び出します。(17 行目)

全てのマーカーを非表示にする事によって、クラスターマーカーにマーカーが含まれなくなり、画面表示の更新後クラスターマーカー自体が表示されなくなります。

下図は「repaint メソッド呼び出し前」と「repaint メソッド呼び出し後」の画像になります。

repaint メソッド呼び出し前
repaint メソッド呼び出し前
repaint メソッド呼び出し後
repaint メソッド呼び出し後
// sample.component.ts
import { Component } from "@angular/core";

@Component({
  selector: "app-sample",
  templateUrl: "./sample.component.html",
  styleUrls: ["./sample.component.scss"],
})
export class SampleComponent {
  @ViewChild("markerClusterer") markerClusterer!: MapMarkerClusterer;

  public markerPositions: google.maps.LatLngLiteral[] = [];

  public toggleMarkers(): void {
    const markers = this.markerClusterer?.markerClusterer?.getMarkers() ?? [];
    for (const marker of markers) marker.setVisible(!marker.getVisible());
    this.markerClusterer?.markerClusterer?.repaint();
  }
}

 

マーカーアニメーション使用時の注意点

マーカーアニメーションを利用している場合に visible プロパティの変更や、クラスタリングライブラリを利用してクラスターマーカーとの表示切り替えを行うと、再表示時にアニメーションが再生されません。

そのため、下記のような形で明示的にアニメーションを再設定する必要があります。

 

マーカーアニメーションとは

マーカーコンポーネントの options.animation プロパティにgoogle.maps.Animation.BOUNCE等の値を代入することにより、マーカーをアニメーションさせる機能です。

google.maps.Animation.BOUNCEを代入した場合、マーカーが上下に動きます。

 

実装手順

  • マーカーコンポーネントの visibleChanged イベント、クラスターマーカーコンポーネントの clusteringend イベントにアニメーションを再設定する関数を設定
  • 設定した関数内で setAnimation メソッドを呼び出す

 

マーカーコンポーネントの visibleChanged イベント、クラスターマーカーコンポーネントの clusteringend イベントに関数を設定

visibleChanged イベント、clusteringend イベントにアニメーションを再設定する関数を呼び出す処理を設定します。(7、13 行目)

visible プロパティが変更される、またはクラスタリングの処理が終了した際に、設定した関数が呼び出されます。

<!-- sample.component.html -->
<google-map>
  <map-marker-clusterer
    #markerClusterer="mapMarkerClusterer"
    imagePath="assets/images/m"
    [ignoreHidden]="true"
    (clusteringend)="setMarkersAnimation()"
  >
    <ng-container *ngFor="let position of markerPositions">
      <map-marker
        #marker="mapMarker"
        [position]="position"
        (visibleChanged)="setMarkerAnimation(marker)"
      ></map-marker>
    </ng-container>
  </map-marker-clusterer>
</google-map>

 

設定した関数内で setAnimation メソッドを呼び出す

typescript ファイル内で@ViewChild を使用し、html ファイルにある map-marker コンポーネント、map-marker-clusterer コンポーネントを取得します。(10、11 行目)

マーカーに対して setAnimation メソッドを呼び出し、アニメーションを再設定します。(16、22 行目)

// sample.component.ts
import { Component } from "@angular/core";

@Component({
  selector: "app-sample",
  templateUrl: "./sample.component.html",
  styleUrls: ["./sample.component.scss"],
})
export class SampleComponent {
  @ViewChild("markerClusterer") markerClusterer!: MapMarkerClusterer;
  @ViewChild("mapMarker") marker!: MapMarker;

  public markerPositions: google.maps.LatLngLiteral[] = [];

  public setMarkerAnimation(marker: MapMarker): void {
    this.marker.marker?.setAnimation(google.maps.Animation.BOUNCE);
  }

  public setMarkersAnimation(): void {
    const markers = this.markerClusterer?.markerClusterer?.getMarkers() ?? [];
    for (const marker of markers)
      marker.setAnimation(google.maps.Animation.BOUNCE);
  }
}

 

あとがき

本記事でご紹介した設定以外にクラスターマーカーのフォント等、表示面でも細かく設定することが可能です。 下記関連リンクのClusterIconStyleから確認できますので、ぜひ試してみて下さい。

 

にTypeScriptでのフロントエンド開発を担当:木戸裕貴

木戸裕貴

私は主にTypeScriptでのフロントエンド開発を担当しております。

シェアする
記事カテゴリ
最新記事
2025.04.30

Power Apps, Power Automate で作る NFC タグを活用したアプリ例

2025.04.16

Power Apps で NFC タグを使ってみる

2025.04.02

Copilot Studioで作成したコパイロットをTeams に追加する方法

2025.03.19

SharePoint リストで主キーを実装し、比較してみた

2025.03.12

SharePointのデザインをもっとおしゃれに!(X-SP Design | SharePoint デザイン拡張サービスのご紹介)(4) サンプルの紹介その2

SharePointEF CoreMarker Clustererキャンバスアプリメールdialogerrorレスポンシブ レイアウトOpenAI環境構築手順複数項目削除変更生成系AIExcelマイグレーションRANK()関数DatePickerfirst()関数Tips復元responsive layoutオープンAIpipelineシェアポイントフォルダ外部DBCopilotPower AutomateFramework CoreDynamics 365 SalesDropdownnest新機能restoreデータ行の制限チャットGPTCI/CD便利機能ゴミ箱連携licenseC#Attribute directivesMicrosoft Translatorview入れ子変数Power BI引き継ぎgalleryパイプラインカレンダー完全削除接続添付ファイルコントロールattributeO/Rマッパーマーカークラスタリングライブラリビュー動的リスト検索個人列退職ギャラリーDevOpsCalendarモデル駆動型データフローファイルサイズvalidationazure sql databasetailwindcssアクセス制限collectionMicrosoft 365グループユーザー列所有者を変更スクロールMicrosoft 365Teamsセキュリティロールrecycle binフルリモートワークローコードCase式マルチテナント承認コレクションセキュリティグループSharePoint Online異動コンテナ簡易在庫管理ローコード開発ビジネスルールごみ箱アーティサンAngularHTTP Requestドロップダウンメニューリマインド複数の添付ファイル送信元リストLoopショートカットキー時間外非エンジニアDataverseアクセス許可ArtisanAccessCSSBreakpointObserverSet承認フローメールの送信非表示Microsoftshortcut key通知体験談JavaScriptSharePoint Framework転職InfoPathxUnitメディアクエリForAllform差出人アプリdesignconcat関数ファイル勉強表示SPFx主キーMatTable.Net Core 3.1スマホUpdateContextエクスポートインスタントクラウドフロー[市民開発者JSON文字制限フィルター クエリ内製化切替サンプルCopilot StudioAngular MaterialVSCodePCロードマップインポート自動化したクラウドフロー構築デザインフロー実行ドキュメント ライブラリ市民開発登録者samplePowerAppsデータ構造.Net Core Test Explorerレスポンシブ技術カスタマイズ委任自動化したクラウド フロー運用開発環境filter query管理システム列X-SPNFCタグモデル駆動型アプリSortByColumns関数Dataverse for Teams入門ItcomponentVBAフローの種類選択肢列環境sortガバナンス登録日StylePowerAutomatePower AppsTypeScriptitem関数初心者情報技術ダイアログエラーインスタント クラウド フロー参照列本番環境ソートerror notification更新者StudioPower PlatformHTMLGoogle Maps中級者メッセージIDコンポーネントエクセルスケジュール済みクラウド フローChatGPTライセンスmultiple itemエラー通知更新日AI
PageTop
ページトップに戻る