技術情報ブログ
Angular
2021.10.27

Angular×Google Maps:MarkerClustererPlusでクラスタ表示を切り替える方法(第2回)(ignoreHidden / repaint)

Angular×Google Maps:MarkerClustererPlusでクラスタ表示を切り替える方法(第2回)(ignoreHidden / repaint)
木戸裕貴

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

Angular で Google Maps を利用した際に発生しがちな、大量マーカー表示によるUX低下をクラスタリングで回避する方法(後編)です。

本記事では、クラスターマーカーの表示・非表示の切り替え(ignoreHidden / visible / repaint)と、クラスタ切り替え時に起きるマーカーアニメーションが再生されない注意点(visibleChanged / clusteringend で再設定)を、実装例つきで解説します。

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

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

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

Google Maps×Angular の表示パフォーマンスや、クラスタリングのUX設計で詰まっている場合は、要件(表示件数・更新頻度・操作導線)を整理した上で最適な実装方針をご一緒に検討できます。

「大量マーカーをどう軽くするか」「クラスタのON/OFFをどの体験にするか」など、実装と設計の両面から相談可能です。

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でのフロントエンド開発を担当しております。

Microsoftクラウド関連

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

Dataverse入門(5)!モデル駆動型アプリの作り方-キャンバスアプリとの違いは?

2026.03.03

Dataverse入門(4)!代替キーってどんな場面で役に立つの?-データの重複を許さない

2026.02.25

Dataverse:Dataverse入門(3)!リレーションでデータを構造化する-テーブル間の連携とは?

2026.02.18

Dataverse入門(2)!テーブルに列を追加してみる-列の型の決め方

2026.02.11

Dataverse入門(1)!注文管理アプリを作ってみる-Dataverseテーブルの作り方

SharePointEF CoreMarker Clusterer中級者DXカスタマイズ委任自動化したクラウド フロー運用開発環境filter query管理システム列StyleDLPポリシー地方自治体MLJSON書式保守性デジタル化推進複数レコードPCFギャラリー一意制約ExcelマイグレーションRANK()関数キャンバスアプリノウハウcomponentVBAフローの種類選択肢列環境sortガバナンス登録日StudioTestCopilot Studiot共有リンクテンプレート化DX推進テーマカラーPDF変換業務システムMicrosoft DataversePower AutomateFramework CoreDynamics 365 SalesDatePicker情報技術ダイアログエラーインスタント クラウド フロー参照列本番環境ソートerror notification更新者AICanvas自治体DXレポート化サイト複製作り方ダークモード資料自動作成キャンバスアプリ 違いフォーム設定C#Attribute directivesMicrosoft TranslatorDropdownメッセージIDコンポーネントエクセルスケジュール済みクラウド フローChatGPTライセンスmultiple itemエラー通知更新日生成系AITest Studio生成AI自治体APIPnP PowerShellページ承認Formulasプロパティフロー設計Power Apps 導入ビュー設定attributeO/Rマッパーマーカークラスタリングライブラリviewメールdialogerrorレスポンシブ レイアウトOpenAI環境構築手順複数項目削除変更Copilotテスト事例HTTP リクエストカスタムスクリプトドキュメント管理カラーセットテンプレート活用Power Apps 比較Power Apps モデル駆動型validationazure sql databasetailwindcssビューfirst()関数Tips復元responsive layoutオープンAIpipelineシェアポイントフォルダ外部DBlicenseテストスタジオ活用ワーケーション業務効率化IT管理カラーユニバーサルデザイン自動化事例モデル駆動型 とは注文管理アプリローコードCase式マルチテナントアクセス制限nest新機能restoreデータ行の制限チャットGPTCI/CD便利機能ゴミ箱連携添付ファイルコントロール使い方サイトブランド化名古屋ファイル保存申請システムアプリデザインNode.jsシステム構築サイトマップAngularHTTP Requestドロップダウンメニューノーコード入れ子変数Power BI引き継ぎgalleryパイプラインカレンダー完全削除接続ファイルサイズ基本知識フォントカスタマイズ体験記エンティティワークフロー自動化UI/UXVisual Studio CodeAlternate KeyサブグリッドAccessCSSBreakpointObserver承認動的リスト検索個人列退職ギャラリーDevOpsCalendarモデル駆動型データフローフルリモートワークPowerAutomateブランドセンター感想フォルダ構成設定アクセシビリティPCF代替キー業務アプリ開発InfoPathxUnitメディアクエリリマインドcollectionMicrosoft 365グループユーザー列所有者を変更スクロールMicrosoft 365Teamsセキュリティロールrecycle binアーティサンX-SP Designテーマ作成チームサイトMicrosoft Learn Docsアジャイル開発Wordテンプレート環境構築重複チェックDataverse テーブルMatTable.Net Core 3.1スマホSetコレクションセキュリティグループSharePoint Online異動コンテナ簡易在庫管理ローコード開発ビジネスルールアクセス許可Artisanスライドショーデザイン拡張コミュニケーションサイトカスタムコネクタ準委任契約業務自動化カスタムコンポーネントGUIDAngular MaterialVSCodePCForAll複数の添付ファイル送信元リストLoopショートカットキー時間外非エンジニアDataverseSharePoint Framework転職Slide showMicrosoft365サイトの種類OpenAPI請負契約効率化Power Platform CLI業務キーデータ構造.Net Core Test ExplorerレスポンシブUpdateContext承認フローメールの送信非表示Microsoftshortcut key通知体験談JavaScriptSPFx主キー比較移行要件定義MCPサーバー総合評価型入札資料作成開発手順複合キーモデル駆動型アプリSortByColumns関数Dataverse for TeamsDynamics 365ロードマップform差出人アプリdesignconcat関数ファイル勉強表示サンプルCopilot Studio社内ポータル多言語化サイト構成FAQエージェントデジタルトランスフォーメーション初心者向け拡張機能データ整合性Power AppsTypeScriptitem関数入門技術エクスポートインスタントクラウドフロー[市民開発者JSON文字制限フィルター クエリ内製化切替samplePowerAppsグループウェアMUI権限設計AIチャットボットプロポーザル方式ハウツービルドデータベース設計Power PlatformHTMLGoogle Maps初心者Itインポート自動化したクラウドフロー構築デザインフロー実行ドキュメント ライブラリ市民開発登録者X-SPNFCタグエンゲージメントMultilingualデータ移行実運用官公庁システム画像挿入プロジェクト作成ユニークキー
PageTop
ページトップに戻る