Google Maps API の新しい読み込み方と高度なマーカーの使い方
Google Maps JavaScript API の最新バージョンでは、importLibrary() を使った新しい読み込み方法(Dynamic Library Import)と、より柔軟なカスタマイズが可能な「高度なマーカー(Advanced Markers)」が導入されています。以下では、基本的な地図の表示から、高度なマーカーの作成、クリックイベントの追加、カスタム HTML を使った表示、data-* 属性を使って1ページに複数の地図を表示する方法など、最新 API を活用した実装手法を解説しています。
作成日:2025年07月21日
新しい Maps JavaScript API の読み込み方法(importLibrary)
Google Maps JavaScript API は、以下の 3 つの方法で読み込むことができます:
- Dynamic Library Import(動的モジュール読み込み)を使用 ※ 推奨方法
- script タグによる直接読み込み(従来の方法)
- NPM パッケージ @googlemaps/js-api-loader を使用
Google Maps ドキュメント:Maps JavaScript API を読み込む
Dynamic Library Import(importLibrary)を使う方法
この新しい方式では、必要なライブラリだけをモジュール単位で遅延読み込みすることができます。
たとえば、以下のように使用します。
この importLibrary() を使うためには、以下の Google が提供するブートストラップローダを最初に読み込む必要があります。script タグを使わず、ローダーのコード本体を JavaScript や TypeScript ファイルに直接記述しても動作します。実際の使用方法は次項を御覧ください。
<script>
(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
key: "YOUR_API_KEY", // API キーを指定
v: "weekly", // バージョニングを指定
// Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
// Add other bootstrap parameters as needed, using camel case.
});
</script>
このブートストラップローダの役割
上記のコードは次のことを行います:
- google.maps.importLibrary() を使えるようにする
- 指定したライブラリ(例:maps、marker、placesなど)の遅延読み込みを可能にする
- Google Maps API の script タグを動的に <head> に追加し、API を非同期で読み込む
- API の 多重読み込みを防止する
- key や v(バージョン)などのパラメータを URL に適切に付与する
従来の方式との違い
従来の読み込み方法(callback=initMap など)では、グローバル関数を定義し、全ライブラリを一度に読み込んでいました。
一方、新しい方式では、必要なライブラリだけをモジュールとして後から読み込めるため、ページの初期読み込みを高速化できます。また、グローバル関数を定義せずに済み、モダンな JS 開発にも適しています。
ウェブページに地図を追加
Dynamic Library Import を使って、ウェブページの div 要素に地図を追加する例です。
以下では Google Cloud プロジェクトを作成済みで、Google Maps API キーをすでに取得していることを前提としています。
関連ドキュメントページ:Google マップをウェブページに追加する
API の読み込み
HTML ページで以下の Google が提供する script 要素(ブートストラップローダ)を追加し、Dynamic Library Import(モジュール方式)を使って Maps JavaScript API を読み込みます。
<script>
(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
key: "YOUR_API_KEY", // 取得した実際の API キーを指定
v: "weekly", // バージョニングを指定(この例では推奨値の weekly を指定)
// Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
// Add other bootstrap parameters as needed, using camel case.
});
// script 要素を使う場合は、ここに initMap() の定義や呼び出しを記述できます
</script>
- YOUR_API_KEY には、取得した実際の API キーの値を指定します
- バージョニング には、推奨値の weekly を指定しています(最も新しいバージョンが適用される)
- 地図を初期化する関数の定義や呼び出しは script タグ内に記述できます
div 要素と CSS の追加
地図をウェブページ上に表示するため、HTML に地図を表示する div 要素を追加し、この要素を特定するための id 属性(または class 属性)を指定します。id 属性(または class 属性)は JavaScript や CSS でこの要素を参照するのに使用します。この例では id 属性に map を指定します。
<div id="map"></div>
CSS で地図の高さや幅などを設定します。有効な高さを設定しないと、地図は表示されません。パーセントベースのサイズは親ブロック要素から継承するので、注意が必要です。
#map {
height: 300px;
width: 100%;
}
レスポンシブ表示
地図をレスポンシブに表示する1つの方法は、地図を表示する要素(div#map)を親要素で囲み、その親要素を表示の基準としてそのパディング領域に地図を表示します。
以下の例では同じページに複数の地図を表示してもスタイルを適用しやすいように地図を表示する要素に追加で class="gmap" を指定しています。
<div class="map-wrapper">
<div id="map" class="gmap"></div>
</div>
レスポンシブ表示用の以下のようなスタイルを指定します。必要に応じてマージンを追加して中央寄せしたりボーダーなど適宜変更します。親要素の padding-top は padding-bottom でも同じことです。
この CSS を使う場合は、前述の #map に指定した CSS(height: 300px; width: 100%;)は削除します。
4:3 の比率で表示するには 75%(3 ÷ 4 x 100 = 75% )にします。
.map-wrapper {
position: relative; /* 子要素の基準とする */
width:100%;
padding-top:56.25%; /* 幅の 56.25% を高さとする場合(16:9)*/
border: 1px solid #CCC;
}
.map-wrapper .gmap {
position: absolute; /* 親要素のパディング領域に配置 */
width: 100%; /* 親コンテナの幅いっぱいに表示 */
height: 100%; /* 親コンテナの高さいっぱいに表示 */
top: 0;
left: 0;
}
JavaScript を追加
JavaScript で API の読み込みの後に、地図を初期化する関数 initMap() を定義し、呼び出します。
google.maps.importLibrary() は、Google Maps JavaScript API の一部で、ライブラリの読み込みを非同期に行うための関数です。この関数は Promise を返すため、await を使ってライブラリの読み込みが完了するのを待つ必要があります。
そのため、await を使う関数 initMap() は async(非同期関数) として定義する必要があります。
地図(Map インスタンス)は importLibrary() を使って分割代入で取得した Map コンストラクタを使って生成します。オプションオブジェクト(MapOptions)の center(地図の初期の中心)には緯度と経度の座標を指定し、zoom(地図の初期ズームレベル)には使用するズームレベルを指定します。
// グローバル変数 map を宣言(Map インスタンスを格納するため)
let map;
// Google Maps の初期化を行う非同期関数 initMap() を定義
async function initMap() {
// importLibrary() は Promise を返すため、await を使って "maps" ライブラリを読み込み、
// その中から Map コンストラクタを分割代入で取得
const { Map } = await google.maps.importLibrary("maps");
// Map インスタンスを生成し、id="map" の要素に地図を表示
map = new Map(document.getElementById("map"), {
// 地図の中心座標を指定(例:東京タワー周辺)
center: { lat: 35.659012, lng: 139.745433 },
// ズームレベルを指定(15 は市街地レベル)
zoom: 15,
});
}
// 地図の初期化関数を実行
initMap();
- google.maps.importLibrary() はモジュールベースの読み込み方式を使用しており、必要なコンポーネント(たとえば "maps" や "marker")のみを読み込むことでパフォーマンス最適化が可能です。
- async/await は Promise チェーン(.then())よりもコードの可読性を高めるために使われる非同期処理の書き方です。
- モジュール方式(Dynamic Library Import)を使って API を読み込んでいる場合、地図を初期化する関数の名前は任意の名前を付けられます(initMap という名前に 特別な意味はない)。
また、このコードでは initMap() 関数の外からも map 変数にアクセスできるようにするため、map を関数の外に let を使って宣言しています(let は再代入できるので、初期化は後から initMap() 内で可能)。
let map; をグローバルスコープに書いておけば、例えば、次のようなケースで map を再利用できます。
function zoomIn() {
// let map; を参照
map.setZoom(map.getZoom() + 1);
}
document.getElementById('zoom').addEventListener('click', () => {
zoomIn();
});
もし、地図をグローバルに使う必要がないなら、関数内に閉じた形で const を使えばOKです(必要がなければスコープはなるべく限定するべき)。
この例の場合、以下のような地図が表示されます。
複数の地図を表示する
以下は2つの地図を同じページに表示する例です。
id 属性が map1 と map2 の div 要素を HTML に配置し、CSS を設定します。
<div class="map-wrapper">
<div id="map1" class="gmap"></div>
</div>
<div class="map-wrapper">
<div id="map2" class="gmap"></div>
</div>
以下が JavaScript です。
let map1, map2;
async function initMap() {
const { Map } = await google.maps.importLibrary("maps");
map1 = new Map(document.getElementById("map1"), {
center: { lat: 35.659012, lng: 139.745433 },
zoom: 15,
});
map2 = new Map(document.getElementById("map2"), {
center: { lat: 35.710137, lng: 139.810705 },
zoom: 15,
});
}
initMap();
もし地図をグローバルに使う必要がないなら、以下のように変数を関数内に閉じた形で記述すればOKです。
async function initMap() {
const { Map } = await google.maps.importLibrary("maps");
const map1 = new Map(document.getElementById("map1"), {
center: { lat: 35.659012, lng: 139.745433 },
zoom: 15,
});
const map2 = new Map(document.getElementById("map2"), {
center: { lat: 35.710137, lng: 139.810705 },
zoom: 15,
});
}
initMap();
高度なマーカー(Advanced Markers)を追加
Google Maps JavaScript API では、「高度なマーカー(Advanced Marker)」 を使って、より柔軟なマーカーを地図上に表示できます。これを使うには、initMap() を async 関数として定義し、maps ライブラリに加えて marker ライブラリも読み込む必要があります。
地図の初期化と高度なマーカーの設定
- ライブラリの読み込み
- 地図本体を扱う maps ライブラリと、高度なマーカー機能を提供する marker ライブラリを importLibrary() メソッドで読み込みます。
- 地図の生成
- 高度なマーカーを使うには、地図を生成する際に mapId(マップ ID)を指定する必要があります。これは Google Cloud Console で作成できますが、テスト用として "DEMO_MAP_ID" を指定することも可能です。
- マーカーの作成と追加
- 取得した AdvancedMarkerElement クラスを使ってマーカーを生成し、地図に追加します。
async function initMap() {
// 地図ライブラリを読み込む
const { Map } = await google.maps.importLibrary("maps");
// 高度なマーカーを提供する marker ライブラリを読み込む
const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");
// マーカーの設置位置を変数 position に設定(ここでは東京タワー付近)
const position = { lat: 35.659012, lng: 139.745433 };
// AdvancedMarkerElement を使用するには、mapId を指定して地図を生成する必要がある
const map = new Map(document.getElementById("map"), {
center: position, // 地図の中心を指定
zoom: 15, // ズームレベルを指定
mapId: "DEMO_MAP_ID", // 使用するマップスタイルの ID(Google Cloud Console で作成)
});
// 高度なマーカーを生成して地図に追加
const marker = new AdvancedMarkerElement({
position, // マーカーの位置(position: position の短縮記法)
map, // 表示先の地図オブジェクト(map: map の短縮記法)
title: "東京タワー", // マウスオーバー時に表示されるツールチップ
});
}
initMap();
上記の場合、例えば、以下のような地図とマーカーが表示され、マーカーにマウスオーバーすると title に指定したツールチップが表示されます。
AdvancedMarkerElement を使うには mapId の指定が必須です。mapId(マップID)を指定しないと、以下のようにエラーになります。
関連ドキュメントページ
マップID(mapId)
マップ ID は、Google Cloud に保存されている Google マップのスタイル設定と構成設定を表す一意の識別子です。マップ ID を使用して、ウェブサイトやアプリケーションで機能を有効にしたり、地図を管理したり、スタイルを設定したりします。
テスト運用の場合は、上記の例のようにコードで実際の ID の代わりに mapId: "DEMO_MAP_ID"
を使用することもできます。
マップ ID は Google Cloud コンソールのプロジェクトの [マップ管理] ページで、「マップ ID を作成」をクリックして JavaScript、Android、iOS、静的マップなど、必要なプラットフォームごとに作成できます。
関連ドキュメントページ
AdvancedMarkerElement コンストラクター
AdvancedMarkerElement は、Google Maps JavaScript API(Maps JavaScript API v3.54 以降)で提供される高度なカスタマイズ可能なマーカーを生成するためのコンストラクターです。
このコンストラクターには、オプションオブジェクトを渡してマーカーの外観や動作を細かく制御できます。以下は、AdvancedMarkerElement に渡すオプションオブジェクトの主なプロパティとその説明です。
プロパティ名 | 型 | 説明 |
---|---|---|
position | google.maps.LatLng | google.maps.LatLngLiteral など | マーカーを表示する緯度・経度の座標。 |
map | google.maps.Map | このマーカーを追加する Map インスタンス。 |
title | string | マーカーの上に表示されるツールチップテキスト(アクセシビリティ対応も含む。title 属性として反映)。 |
content | HTMLElement | マーカーの見た目を自由にカスタマイズするための HTML 要素。デフォルト: PinElement.element |
gmpClickable | boolean | マーカーをクリック可能にするかどうか。true にするとイベントリスナーが使用可能に。 |
gmpDraggable | boolean | マーカーをドラッグ可能にするかどうか。 |
zIndex | number | マーカーの重なり順(数値が大きいほど前面に表示)。 |
content にカスタム HTML(SVG)を使う
AdvancedMarkerElement の content プロパティには、カスタムの HTML 要素(HTMLElement)を指定できます。これにより、マーカーの見た目を自由にデザインすることができます。
例:SVG を使ったカスタムマーカーの作成
以下のコードは、SVG を含む div 要素を作成し、それをマーカーの content に設定する例です。
// document.createElement() を使って HTML 要素(HTMLElement)を作成
const customContent = document.createElement('div');
// コンテンツに SVG を指定
customContent.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="34" height="34" fill="#c80101" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M2.854 15.854A.5.5 0 0 1 2 15.5V14H.5a.5.5 0 0 1-.354-.854l1.5-1.5A.5.5 0 0 1 2 11.5h1.793l3.103-3.104a.5.5 0 1 1 .708.708L4.5 12.207V14a.5.5 0 0 1-.146.354zM16 3.5a.5.5 0 0 1-.854.354L14 2.707l-1.006 1.006c.236.248.44.531.6.845.562 1.096.585 2.517-.213 4.092-.793 1.563-2.395 3.288-5.105 5.08L8 13.912l-.276-.182A24 24 0 0 1 5.8 12.323L8.31 9.81a1.5 1.5 0 0 0-2.122-2.122L3.657 10.22a9 9 0 0 1-1.039-1.57c-.798-1.576-.775-2.997-.213-4.093C3.426 2.565 6.18 1.809 8 3.233c1.25-.98 2.944-.928 4.212-.152L13.292 2 12.147.854A.5.5 0 0 1 12.5 0h3a.5.5 0 0 1 .5.5z"/>
</svg>`;
// カスタムコンテンツ(SVG)を使って高度なマーカーを作成
const marker = new AdvancedMarkerElement({
position: { lat: 35.658580, lng: 139.745454 }, // マーカーの位置
map, // 表示先の地図(map: map の短縮形)
title: '東京タワー', // ツールチップとして表示されるタイトル
content: customContent, // 上記で作成したカスタムコンテンツ要素を指定
});
- content に指定するのは HTML 要素(HTMLElement)です。文字列を直接渡すことはできません。そのため、document.createElement() などで要素を作成する必要があります。
- SVG を使う場合はインラインで書く方が制御しやすくなります。
- <img src="data:image/svg+xml;base64,..."> のように img タグで Base64 エンコードした SVG を使う方法もありますが、インライン SVG の方が、fill や stroke などのスタイルを CSS や属性で簡単に変更できます。
- SVG を使うときは以下の属性の設定に注意してください:
- width / height: 表示サイズを明示的に指定
- fill: 塗りの色
- viewBox: スケーリングや表示範囲に必要
async function initMap() {
const { Map } = await google.maps.importLibrary("maps");
const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");
const position = { lat: 35.658580, lng: 139.745454 };
const map = new Map(document.getElementById("map"), {
center: position,
zoom: 15,
mapId: "DEMO_MAP_ID", // 使用するマップスタイルの ID(Google Cloud Console で作成)
});
// document.createElement() を使って HTML 要素(HTMLElement)を作成
const customContent = document.createElement('div');
// コンテンツに SVG を指定
customContent.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="34" height="34" fill="#c80101" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M2.854 15.854A.5.5 0 0 1 2 15.5V14H.5a.5.5 0 0 1-.354-.854l1.5-1.5A.5.5 0 0 1 2 11.5h1.793l3.103-3.104a.5.5 0 1 1 .708.708L4.5 12.207V14a.5.5 0 0 1-.146.354zM16 3.5a.5.5 0 0 1-.854.354L14 2.707l-1.006 1.006c.236.248.44.531.6.845.562 1.096.585 2.517-.213 4.092-.793 1.563-2.395 3.288-5.105 5.08L8 13.912l-.276-.182A24 24 0 0 1 5.8 12.323L8.31 9.81a1.5 1.5 0 0 0-2.122-2.122L3.657 10.22a9 9 0 0 1-1.039-1.57c-.798-1.576-.775-2.997-.213-4.093C3.426 2.565 6.18 1.809 8 3.233c1.25-.98 2.944-.928 4.212-.152L13.292 2 12.147.854A.5.5 0 0 1 12.5 0h3a.5.5 0 0 1 .5.5z"/>
</svg>`;
// カスタムコンテンツ(SVG)を使って高度なマーカーを作成
const marker = new AdvancedMarkerElement({
position, // マーカーの位置
map, // 表示先の地図(map: map の短縮形)
title: '東京タワー', // ツールチップとして表示されるタイトル
content: customContent, // 上記で作成したカスタムコンテンツ要素を指定
});
}
initMap();
マーカー全体を SVG で置き換えるのではなく、グリフ部分を SVG で指定することもできます。
マーカーの基本的なカスタマイズ
Google Maps JavaScript API では、高度にカスタマイズされたマーカーを表示するために、2つの専用クラスを使用します。
- AdvancedMarkerElement クラス:マーカーの基本情報(位置、タイトル、地図など)を定義。
- PinElement クラス:マーカーの見た目(SVGピン)をカスタマイズするためのクラス。
PinElement クラスの読み込み
これらのクラス(AdvancedMarkerElement と PinElement)は marker ライブラリに含まれているため、使用する前に importLibrary('marker') を通じて読み込む必要があります。
PinElementOptions の主なカスタマイズ項目
PinElement クラスでは、以下のオプションを指定してピンのデザインをカスタマイズできます。
- scale:ピン全体のサイズ(例:1.0 が標準)
- background:ピンの背景色
- borderColor:ピンの枠線の色
- glyphColor:ピン中央のアイコン(グリフ)の色
- glyph:ピン中央に表示される DOM 要素(タイプ: string|Element|URL)
マーカーの表示方法
カスタマイズしたピン(PinElement)を AdvancedMarkerElement の content プロパティに指定することで、独自デザインのマーカーを地図上に表示できます。
async function initMap() {
// maps ライブラリ(地図機能)を読み込み
const { Map } = await google.maps.importLibrary("maps");
// marker ライブラリ(カスタムマーカー機能)を読み込み
const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker");
const position = { lat: 35.659012, lng: 139.745433 };
// 地図を初期化
const map = new Map(document.getElementById("map"), {
center: position,
zoom: 15,
mapId: "DEMO_MAP_ID", // 実際の Map ID に置き換えてください
});
// PinElement を使ってカスタムピンのデザインを設定
const pin = new PinElement({
scale: 1.6, // ピンのサイズ(1.0 が標準)
background: '#35e352', // ピンの背景色
borderColor: '#094e15', // ピンの枠線色
glyphColor: '#094e15', // グリフ(アイコンまたは文字)の色
});
// 高度なマーカーを作成し、ピンの要素を content に指定
const marker = new AdvancedMarkerElement({
position,
map,
content: pin.element, // カスタマイズしたピン(PinElement)を指定
});
}
initMap();
上記の場合、例えば、以下のように緑色で大きめのサイズのマーカーが表示されます。
関連ドキュメントページ
グリフにテキストを表示
ピンの中央に表示されるグリフ(アイコン)をテキストに変更したい場合は、PinElement の glyph オプションを使用します。このオプションには、数字やアルファベットなどの任意の文字や HTML 要素を指定できます。
このテキストグリフは PinElement によって描画され、文字の色は glyphColor オプションで設定します。glyphColor を省略した場合は、デフォルトの色が使用されます。
const pin = new PinElement({
scale: 1.6, // ピンのサイズ(1.0 が標準)
background: '#057a19', // ピンの背景色
borderColor: '#094e15', // ピンの枠線色
glyphColor: '#ffffff', // グリフ(アイコンまたは文字)の色
glyph: 'G' // グリフをテキスト文字に
});
例えば、以下のように表示されます。
絵文字(例 😀)や Unicode 文字(例 ♫)も glyph プロパティに指定して表示できます。
但し、JavaScript では U+1F408 のような サロゲートペアの Unicode は glyph: "\uD83D\uDC08" のように指定する必要があります。または、🐈 のように直接文字として渡すのが簡単です。
HTML エンティティ形式で glyph: "🐈" のように渡してもただの文字列として扱われます。
グリフを非表示にする方法:
- glyph を空文字('')に設定する
- または glyphColor を background と同じ色に設定する
グリフに SVG を表示
SVG を PinElementOptions.glyph に指定することは可能ですが、glyph に SVG を直接文字列として埋め込むことはできません。
以下のように SVG を文字列指定すると、SVG 画像ではなく、その文字列が表示されてしまいます。
// これは動作しません(文字列を直接指定している)
const pin = new google.maps.marker.PinElement({
glyph: `<svg ...>...</svg>`, //指定した文字列が表示されてしまう
});
google.maps.marker.PinElement の glyph プロパティは、string | HTMLElement を受け取れます。
SVG をアイコンに使う場合は、以下のように SVG を <div> の innerHTML として渡す方法が簡単です。
SVG の幅や高さは width と height、色は fill 属性で指定することができます。
// document.createElement() を使って HTML 要素(HTMLElement)を作成
const svgDiv = document.createElement('div');
// innerHTML でコンテンツに SVG(Magic アイコン)を指定
svgDiv.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#3764ce" viewBox="0 0 16 16">
<path d="M9.5 2.672a.5.5 0 1 0 1 0V.843a.5.5 0 0 0-1 0zm4.5.035A.5.5 0 0 0 13.293 2L12 3.293a.5.5 0 1 0 .707.707zM7.293 4A.5.5 0 1 0 8 3.293L6.707 2A.5.5 0 0 0 6 2.707zm-.621 2.5a.5.5 0 1 0 0-1H4.843a.5.5 0 1 0 0 1zm8.485 0a.5.5 0 1 0 0-1h-1.829a.5.5 0 0 0 0 1zM13.293 10A.5.5 0 1 0 14 9.293L12.707 8a.5.5 0 1 0-.707.707zM9.5 11.157a.5.5 0 0 0 1 0V9.328a.5.5 0 0 0-1 0zm1.854-5.097a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L8.646 5.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0l1.293-1.293Zm-3 3a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L.646 13.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0z"/>
</svg>`;
// PinElement を作成
const pin = new google.maps.marker.PinElement({
glyph: svgDiv, // 上記で作成した SVG をコンテンツに持つ div 要素を指定
background: "white", // ピンの背景色
borderColor: "orange", // 枠線色
});
// 高度なマーカーを作成し、ピンの要素を content に指定
const marker = new AdvancedMarkerElement({
position,
map,
content: pin.element, // カスタマイズしたピン(PinElement)を指定
});
async function initMap() {
const { Map } = await google.maps.importLibrary("maps");
const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker");
const position = { lat: 35.659012, lng: 139.745433 };
const map = new Map(document.getElementById("map"), {
center: position,
zoom: 15,
mapId: "DEMO_MAP_ID", // 実際の Map ID に置き換えてください
});
// document.createElement() を使って HTML 要素(HTMLElement)を作成
const svgDiv = document.createElement('div');
// コンテンツに SVG を指定
svgDiv.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#3764ce" viewBox="0 0 16 16">
<path d="M9.5 2.672a.5.5 0 1 0 1 0V.843a.5.5 0 0 0-1 0zm4.5.035A.5.5 0 0 0 13.293 2L12 3.293a.5.5 0 1 0 .707.707zM7.293 4A.5.5 0 1 0 8 3.293L6.707 2A.5.5 0 0 0 6 2.707zm-.621 2.5a.5.5 0 1 0 0-1H4.843a.5.5 0 1 0 0 1zm8.485 0a.5.5 0 1 0 0-1h-1.829a.5.5 0 0 0 0 1zM13.293 10A.5.5 0 1 0 14 9.293L12.707 8a.5.5 0 1 0-.707.707zM9.5 11.157a.5.5 0 0 0 1 0V9.328a.5.5 0 0 0-1 0zm1.854-5.097a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L8.646 5.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0l1.293-1.293Zm-3 3a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L.646 13.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0z"/>
</svg>`;
// PinElement を作成
const pin = new google.maps.marker.PinElement({
glyph: svgDiv, // 上記で作成した SVG をコンテンツに持つ div 要素を指定
background: "white", // ピンの背景色
borderColor: "orange", // 枠線色
});
// 高度なマーカーを作成し、ピンの要素を content に指定
const marker = new AdvancedMarkerElement({
position,
map,
content: pin.element, // カスタマイズしたピン(PinElement)を指定
});
}
initMap();
上記の例の場合、例えば、以下のように表示されます。
グリフではなく独自のアイコンやスタイルを使いたい場合は、画像を使ったカスタムマーカーや、HTML + CSS を使ったマーカーの作成も可能です。
関連ドキュメントページ
マーカーにクリックイベントを設定
マーカーは、クリックやドラッグなどの操作に反応させることができます。
以下は、マーカーをクリックしたときに情報ウィンドウ(InfoWindow)を表示する方法(例)です。
まず、情報ウィンドウ(InfoWindow) は maps ライブラリに用意されているコンストラクタを使って作成します。表示する内容(テキストやHTMLなど)は、content プロパティで指定できます。
マーカーをクリック可能にするには、マーカー作成時に gmpClickable: true を設定します。
その上で、クリックイベントを設定します。イベント内では、まず infoWindow.close() を呼び出して、他の場所で開いている情報ウィンドウを閉じておきます。これは、複数のウィンドウが同時に開いて重ならないようにするためです。
次に、infoWindow.open(map, marker) を使って、現在クリックされたマーカーの位置に情報ウィンドウを表示します。
async function initMap() {
// maps ライブラリから Map と InfoWindow を読み込み
const { Map, InfoWindow } = await google.maps.importLibrary("maps");
// Marker ライブラリから AdvancedMarkerElement と PinElement を読み込み
const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker");
// 東京タワーの緯度・経度を定義
const position = { lat: 35.659012, lng: 139.745433 };
// 地図を初期化(表示する HTML 要素とオプションを指定)
const map = new Map(document.getElementById("map"), {
center: position, // 地図の中心位置
zoom: 15, // ズームレベル(数値が大きいほど拡大)
mapId: "DEMO_MAP_ID", // Google Cloud Console で作成したマップIDに置き換える
});
// ピンの見た目をカスタマイズ(色やサイズなど)
const pin = new PinElement({
scale: 1.6, // ピンの拡大率(1.0 が標準サイズ)
background: '#ed6bc4', // ピンの背景色
borderColor: '#7a0d57', // ピンの縁の色
glyphColor: '#7a0d57', // 中央のグリフ(記号や文字)の色
// glyph オプションを使えば文字やアイコンを指定可能
});
// カスタムピンを使って高度なマーカーを作成
const marker = new AdvancedMarkerElement({
position, // マーカーの位置
map, // 表示先の地図
title: '東京タワー', // ツールチップとして表示されるタイトル
content: pin.element, // カスタムピン要素を指定
gmpClickable: true, // クリックイベントを有効にする(※ この場合は必須)
});
// 情報ウィンドウ(InfoWindow)を作成
const infoWindow = new InfoWindow({
content: `
<div style="padding: 8px 12px; font-size: 14px;">
東京タワー<br>
<a href="https://www.tokyotower.co.jp/" target="_blank" rel="noopener noreferrer">
公式サイトを見る
</a>
</div>
`
});
// infoWindow.open(map, marker); // InfoWindow を初期状態で表示する場合は、コメントを削除
// マーカーがクリックされたときに情報ウィンドウを表示
marker.addListener('click', () => {
// 既に開いている infoWindow を確実に閉じてから再表示
infoWindow.close();
infoWindow.open(map, marker);
});
}
// 関数を呼び出して地図を初期化
initMap();
情報ウィンドウ(InfoWindow)の作成
InfoWindow は maps ライブラリから提供されており、次のように作成します。
content プロパティには表示したいテキストや HTML を指定できます。
const infoWindow = new google.maps.InfoWindow({
content: 'ここに表示する内容(テキストやHTML)'
});
マーカーのクリック時に InfoWindow を表示する手順
- marker.addListener('click', ...) を使ってマーカーにクリックイベントを設定します。
- イベントの中で、まず infoWindow.close() を呼び出して、すでに開いているウィンドウがあれば閉じます。
- 続いて infoWindow.open(map, marker) を使って、現在クリックされたマーカーの位置に InfoWindow を表示します。
これは、複数のマーカーがある場合でも、前に開かれた InfoWindow を閉じてから新しく表示することで、ウィンドウが重なって表示されないようにするためです。
このようにすることで、ユーザーがマップ上のマーカーをクリックするたびに、常に最新の情報ウィンドウだけが表示されるようになります。
open() の第1引数は情報ウィンドウがどの地図上に表示されるかを指定し、第2引数には情報ウィンドウを「アンカー」として紐づけるオブジェクト(通常は Marker インスタンス)を指定します。
InfoWindow を初期状態で表示する
InfoWindow を初期状態で(はじめから)表示するには、InfoWindow を作成(定義)した後で、以下を記述します。
infoWindow.open(map, marker);
例えば、以下のように表示されます。
マーカーごとに情報ウィンドウを作成
必要に応じて、マーカーごとに InfoWindow を作成することもできます。
以下は個々のマーカーに InfoWindow を作成して、初期状態で全て表示する例です。
async function initMap() {
// 地図と情報ウィンドウのライブラリを読み込み
const { Map, InfoWindow } = await google.maps.importLibrary("maps");
// 高度なマーカー(AdvancedMarkerElement)とピン要素(PinElement)を読み込み
const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker");
// 地図を初期化して表示
const map = new Map(document.getElementById("map"), {
center: { lat: 35.659012, lng: 139.745433 }, // 地図の中心座標(東京タワー)
zoom: 15, // ズームレベル
mapId: "DEMO_MAP_ID", // 使用するマップID(Google Cloud Consoleで発行)
});
// 複数のマーカーの情報を格納したオプション配列(高度なマーカーとピン要素の生成に使用)
const options = [
{
position: { lat: 35.659012, lng: 139.745433 },
title: "東京タワー",
background: '#ed6bc4',
borderColor: '#7a0d57',
glyphColor: '#7a0d57',
},
{
position: { lat: 35.657373, lng: 139.748265 },
title: "増上寺",
background: 'lightgreen',
borderColor: 'darkgreen',
glyphColor: 'darkgreen',
},
{
position: { lat: 35.660069, lng: 139.736378 },
title: "六本木ミュージアム",
background: 'lightblue',
borderColor: 'blue',
glyphColor: 'blue',
},
];
// オプション配列からマーカーを順に生成
options.forEach(({ position, title, background, borderColor, glyphColor }, i) => {
// カスタムピンを作成(色・番号付き)
const pin = new PinElement({
scale: 1.5, // サイズを拡大
background, // 背景色
borderColor, // 枠線の色
glyphColor, // 中央の文字色
glyph: `${i + 1}`, // 1から始まる連番を表示
});
// AdvancedMarkerElement を使ってカスタムマーカーを作成
const marker = new AdvancedMarkerElement({
position, // マーカーの位置
map, // 表示する地図
title: `${i + 1}. ${title}`, // タイトル(InfoWindow で表示)
content: pin.element, // ピン要素のDOMを使ってカスタム表示
gmpClickable: true, // クリック可能に設定
});
// InfoWindow インスタンスをそれぞれに作成
const infoWindow = new InfoWindow();
// InfoWindow の重なり順の制御(i が 0 の東京タワーのウィンドウを前面に)
if (i === 0) {
infoWindow.setZIndex(10); //
}
// タイトルを InfoWindow にセット
infoWindow.setContent(marker.title);
// 指定のマーカー位置に InfoWindow を開く(初期状態で表示)
infoWindow.open(marker.map, marker);
// マーカークリック時のイベントリスナーを登録
marker.addListener('click', () => {
infoWindow.close(); // すでに開いている InfoWindow を閉じる
infoWindow.setContent(marker.title); // タイトルを InfoWindow にセット
infoWindow.open(marker.map, marker); // 指定のマーカー位置に InfoWindow を開く
});
});
}
// 関数を実行して地図を初期化
initMap();
InfoWindow の重なり順
この例の場合、2つのマーカーの位置が近いため、情報ウィンドウが重なってしまうため、setZIndex メッソッドを使って、infoWindow.setZIndex(10); のように指定して重なり順を制御しています。
※ プロパティを使って、infoWindow.zIndex = 10 のように指定しても機能しません。
上記の場合、以下のように表示されます。それぞれの情報ウィンドウは独立しているので、個々に表示・非表示をコントロールできます。
また、デフォルトでは 2 の「増上寺」の情報ウィンドウが前面に表示されますが、setZIndex メッソッドを使って 1 の「東京タワー」の情報ウィンドウを全面に表示しています。
関連ドキュメントページ
data 属性で制御する Googleマップ表示
gmap クラスを指定した(複数の)要素の data 属性の値を使って、Googleマップを表示する例です。
このコードは、HTML 内に配置された複数の <div class="gmap" ...> 要素に対して、それぞれ独立した Google マップを表示し、カスタマイズ可能なマーカー(AdvancedMarker + PinElement)と InfoWindow を動的に設定するものです。
- data-lat, data-lng, data-zoom に基づいてマップを表示。
- data-background, data-border-color, data-glyph-color, data-glyph, data-scale を指定することでピンの外観を制御。
- data-title を使って InfoWindow に表示するテキストを設定。
- 共通の InfoWindow を使って複数マーカーで使いまわし。
async function initMap() {
// 全ての地図要素(.gmap クラスの要素)を取得
const gmapElems = document.querySelectorAll(".gmap");
// .gmap 要素が 1 つもなければ何もせず終了(早期リターン)
if (gmapElems.length === 0) return;
// 必要なライブラリを非同期で読み込み
const { Map, InfoWindow } = await google.maps.importLibrary("maps");
const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker");
// 実際の Map ID に差し替える必要があります(Google Cloud Console で取得)
const mapId = "DEMO_MAP_ID";
// 複数地図で異なる mapId を使いたい場合
// const mapId = elem.dataset.mapId || "実際の Map ID";
// マップ全体で共通の情報ウィンドウを作成(使いまわす→または forEach 内で個別に生成)
const infoWindow = new InfoWindow();
// 各地図要素に対してマップを初期化
gmapElems.forEach((elem) => {
// data-lat とdata-lng 属性の値を数値に変換して中心座標を取得
const lat = parseFloat(elem.dataset.lat);
const lng = parseFloat(elem.dataset.lng);
// lat または lng のいずれかが数値でなければ中断
if (isNaN(lat) || isNaN(lng)) {
console.warn(`Invalid lat/lng detected in element`, elem);
return;
}
// lat または lng を使って position を作成
const position = { lat, lng };
// ズームレベルを取得(なければ15を使用)
const zoom = elem.dataset.zoom ? Number(elem.dataset.zoom) : 15;
// 地図を作成
const map = new Map(elem, {
center: position,
zoom,
mapId,
});
// ピンのオプションのデフォルト値
const defaultPinOptions = {
scale: 1.0,
background: '#ec3127',
borderColor: '#992a19',
glyphColor: '#992a19',
};
// data 属性から値を取得し、なければデフォルトを使う
const scalVal = elem.dataset.scale;
// data-scale が空の場合や数値でない場合は、デフォルト値を使う
const scale = scalVal !== "" && !isNaN(Number(scalVal)) ? Number(scalVal) : defaultPinOptions.scale;
const background = elem.dataset.background || defaultPinOptions.background;
const borderColor = elem.dataset.borderColor || defaultPinOptions.borderColor;
const glyphColor = elem.dataset.glyphColor || defaultPinOptions.glyphColor;
const glyph = elem.dataset.glyph; // 設定されていれば、PinElement 生成後に上書きする
// カスタムピン(グリフはデフォルト)を作成
const pin = new PinElement({
scale,
background,
borderColor,
glyphColor,
});
// data-glyph が設定されていれば glyph プロパティ(グリフ)を上書き
if (glyph) pin.glyph = glyph;
// data-title からタイトル(InfoWindow の内容)を取得
const title = elem.dataset.title ? elem.dataset.title : '';
// 高度なマーカーを作成し、ピンをカスタム内容として設定
const marker = new AdvancedMarkerElement({
position,
map,
title,
content: pin.element, // ピン要素を content に設定
});
// マーカークリックで InfoWindow を開く
marker.addListener('click', () => {
// 既存の InfoWindow があれば閉じる(重複防止)
infoWindow.close();
// InfoWindow にマーカーのタイトルを表示
infoWindow.setContent(marker.title);
// マーカーの位置に InfoWindow を開く
infoWindow.open(marker.map, marker);
});
});
}
// 地図の初期化を実行
initMap();
処理の流れ
- 対象のマップ要素を取得
- .gmap クラスのすべての要素を document.querySelectorAll() で取得。
- マップ要素が存在しなければ早期リターン
- マップ要素の数が0であれば、関数を何もせず終了。不要な初期化やライブラリ読み込みを防ぐ。
- Google Maps API のモジュール読み込み(非同期)
- maps モジュールから:Map, InfoWindow
- marker モジュールから:AdvancedMarkerElement, PinElement
- 各 .gmap 要素に対して処理
- forEach() でループし、以下の処理を個別に実施。
各マップ要素ごとの処理
- マップの初期化
- data-lat, data-lng から中心座標を取得。
- 不正な座標値(isNaN())がある場合は console.warn() を出してスキップ。
- data-zoom があればそれを使い、なければズームレベル 15。
- ピンのオプション設定
- デフォルト値(赤いピン→必要に応じて変更)を用意。
- data-* 属性があればそれらで上書き。
- data-scale に関しては数値かどうかを isNaN() で判定して Number() に変換。
- PinElement の作成
- スケール・色をカスタマイズしたピンを生成。
- data-glyph があればグリフも設定。
- AdvancedMarkerElement の作成
- マップにピンを表示し、title を設定。
- 共通の InfoWindow を使ってマーカークリック時に情報表示
- 共通の InfoWindow を使い、クリックでタイトル表示
- 前のウィンドウがあれば閉じてから開く
特徴
- 複数の .gmap 要素に対応しており、1ページに複数の地図を表示可能。場所やズームレベル、タイトルなどを data-* 属性で個別に指定。
- ピンのスタイルも HTML の data-* 属性で個別に指定できるため、マーカーの見た目をHTMLだけで簡単にカスタマイズ可能。
- 共通の InfoWindow を使う設計で、パフォーマンスにも配慮。
- mapId は data-map-id を使って地図ごとに変えることも可能(コメントアウト済みの箇所を使用)。
使い方
Google マップを表示したい場所に、class="gmap" と data-lat="xxxx" 及び data-lng="xxxx" 属性を指定した div 要素を配置します。gmap クラスと data-lat 及び data-lng 属性は必須です。
data-lat と data-lng 属性が指定されていない場合や値が無効な場合は、地図は表示されません。
以下は指定可能なカスタムデータ(data-*)属性です。
data-* 属性 | 説明 |
---|---|
data-lat | 地図の中心の緯度(必須) |
data-lng | 地図の中心の経度(必須) |
data-zoom | 地図の初期ズームレベル(0~20 の間の数値) |
data-scale | ピン全体のサイズ(例:1.0 が標準) |
data-background | ピンの背景色 |
data-borderColor | ピンの枠線の色 |
data-glyphColor | ピン中央のアイコン(グリフ)の色 |
data-glyph | ピン中央に表示するテキスト |
data-title | ロールオーバーテキスト(マーカーにマウスオーバー時に表示されるツールチップ) |
例えば、以下のような HTML をページに記述します。この例では、地図をレスポンシブ表示するために、div.gmap(地図を表示する要素)を div.map-wrapper でラップしています。
<div class="map-wrapper">
<div class="gmap" data-lat="36.238644" data-lng="137.968878" data-title="松本城"></div>
</div>
<div class="map-wrapper">
<div class="gmap" data-lat="35.659012" data-lng="139.745433" data-title="東京タワー" data-zoom="16" data-glyph="A" data-glyph-color="#fff"></div>
</div>
<div class="map-wrapper">
<div class="gmap" data-lat="35.710175" data-lng="139.810700" data-title="スカイツリー" data-background="lightgreen" data-scale="1.3" data-zoom="18"></div>
</div>
上記の場合、以下のような3つの地図が表示されます。