Google Maps APIを使用してクリーンで見やすいカスタムマップを作成する方法

## はじめに
ウェブやモバイルアプリケーションにおけるマッピング機能は、ユーザー体験の中核をなす要素の一つです。Google Maps APIはそのマッピング機能を提供し、様々なカスタマイズを可能にするツールです。通常、Google Mapsのデフォルト設定では、地図上に駅名、地名、ビル名などの詳細が豊富に表示されます。しかし、特定のプロジェクトでは、これらの情報が多すぎて逆にユーザーの目的に沿わない場合もあります。

今回は、[合同会社モテアソブ三軒茶屋](https://moteasobu.jp/home)からの特別な依頼を受け、千住浪漫シティプロジェクトの一環として、よりスッキリとしたデザインのカスタムマップを作成しました。このプロジェクトは、地域の魅力を再発見し、訪れる人々に新たな体験を提供することを目指しています。作成したカスタムマップは、「千住浪漫シティ」の[公式サイト](https://senjuroman.city/)にてご覧いただけます。

この記事では、その制作過程で用いたGoogle Maps APIの詳細設定とコードについて、わかりやすく解説していきます。

<br>

![2023-11-07 21.20.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487238/4af4b588-86bc-1841-e498-d2440c7ba9bd.png)
_初期状態のマップ_

![2023-11-07 21.22.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487238/ff9f90ad-5e90-f941-8f0f-2237c35c1b2d.png)
_デザイン後のカスタムマップ_

## カスタムマップの初期設定
カスタマイズされたマッピング機能を実装するには、まずGoogle Mapsを埋め込むHTML構造と、マップを操作するJavaScriptの読み込みが必要です。このセクションではそれらの基本的な設定手順を解説します。

### HTMLの設定
HTMLでは、マップを表示するための`<div>`タグを設定し、さらにJavaScriptファイルを読み込むための基本テンプレートを用意します。

```html:index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Custom Google Map</title>
  <link rel="stylesheet" type="text/css" href="style.css">
  <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
</head>
<body>
  <div id="map"></div>
  <!-- その他の要素 -->
  <script src="./script.js" defer></script>
</body>
</html>
```

### マップの表示場所（コンテナ）
マップが表示される場所は、`<div id="map"></div>`という要素によってHTMLに定義されます。この`<div>`は、CSSを通じてスタイルを設定し、ページ上でのサイズと位置を定義することができます。

```html:html
<div id="map"></div>
```
という要素によってHTMLに定義されます。この`<div>`タグにスタイルを適用することで、マップの幅、高さ、ボーダーなどをカスタマイズできます。たとえば、以下のようにCSSでスタイルを指定できます。

```css:css
#map {
  height: 400px; /* マップの高さを指定 */
  width: 100%; /* マップの幅を親要素の幅に合わせて指定 */
}
```
以上の設定により、Google Maps APIを適切に読み込み、マップをページ上の指定された場所に表示する準備が整います。これで、JavaScriptを使ってマップのカスタマイズや機能の追加に進むことができます。

### Google Maps APIの読み込み
```html:html
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
```

YOUR_API_KEYの部分は、Google Cloud Platformで取得した独自のAPIキーに置き換える必要があります。APIキーは、Google Mapsの機能を使用するためのアクセス許可として機能します。

### カスタムスクリプトの読み込み
```html:html
<script src="./script.js" defer></script>
```

カスタムスクリプト、すなわち地図の設定や操作を行うためのJavaScriptファイルを読み込みます。defer 属性を使用することで、全てのHTMLが解析された後にスクリプトが実行されるようになり、ページの読み込みを高速化することができます。

これらの設定によって、地図を表示し、カスタマイズするための土台が整いました。次に、実際にJavaScriptを使って地図のカスタマイズ方法について詳しく見ていきましょう。

## カスタムスクリプトの設定

以下のJavaScript関数 initMapでカスタムマップを初期化するための基本的な設定を行います。

```javascript:script.js
function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
  
    // 地図の中心点を指定します。緯度と経度で位置を定めます。
    center: { lat: 35.7447721, lng: 139.8003518 },

    // 地図のズームレベルを指定します。1が最も離れた地球全体を示し、20が最も近いズームレベルです。
    // 通常の街角の表示には13から15が推奨されます。
    zoom: 13,

    // ストリートビューのコントロールを表示するかどうかを決めます。
    // falseに設定すると、ストリートビューを起動するためのUIが非表示になります。
    streetViewControl: false, 

    // カスタムスタイルを指定することで、地図の見た目をカスタマイズできます。
    styles: [...]
    
  });
}
```

全体のコードとスタイル配列はかなり長くなりますので、確認したい方を折りたたみから参照してください。

<details><summary>全体のコードを表示（折りたたみ）</summary><div>

```javascript:script.js

function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
  
    // 地図の中心点を指定します。緯度と経度で位置を定めます。
    center: { lat: 35.7447721, lng: 139.8003518 },

    // 地図のズームレベルを指定します。1が最も離れた地球全体を示し、20が最も近いズームレベルです。
    // 通常の街角の表示には13から15が推奨されます。
    zoom: 13,

    // ストリートビューのコントロールを表示するかどうかを決めます。
    // falseに設定すると、ストリートビューを起動するためのUIが非表示になります。
    streetViewControl: false, 
    
    // カスタムスタイルを指定することで、地図の見た目をカスタマイズできます。
    styles: [
      {
        "featureType": "water",
        "stylers": [{ "color": "#E0EDF5" }, { "visibility": "on" }]
      },
      {
        "featureType": "landscape.man_made",
        "elementType": "geometry.fill",
        "stylers": [{ "color": "#F7F7F7" }, { "visibility": "on" }]
      },
      {
        "featureType": "landscape.natural",
        "stylers": [{ "color": "#F7F7F7" }, { "visibility": "on" }]
      },
      {
        "featureType": "administrative.province",
        "elementType": "geometry.stroke",
        "stylers": [{ "color": "#5F6368" }, { "visibility": "on" }]
      },
      {
        "featureType": "administrative.locality",
        "elementType": "labels",
        "stylers": [{ "visibility": "on" }]
      },
      {
        "featureType": "administrative.locality",
        "elementType": "labels.text.fill",
        "stylers": [{ "color": "#858585" }, { "visibility": "on" },]
      },
      {
        "featureType": "poi",
        "stylers": [{ "visibility": "off" }]
      },
      {
        "featureType": "poi.park",
        "elementType": "labels",
        "stylers": [{ "visibility": "off" }]
      },
      {
        "featureType": "road",
        "elementType": "labels",
        "stylers": [{ "visibility": "off" }]
      },
      {
        "featureType": "road.arterial",
        "elementType": "labels",
        "stylers": [{ "visibility": "off" }]
      },
      {
        "featureType": "road.highway",
        "elementType": "labels",
        "stylers": [{ "visibility": "off" }]
      },
      {
        "featureType": "road.highway.controlled_access",
        "elementType": "labels",
        "stylers": [{ "visibility": "off" }]
      },
      {
        "featureType": "road.local",
        "stylers": [{ "color": "#FFFFFF" }, { "visibility": "on" }
        ]
      },
      {
        "featureType": "road",
        "elementType": "geometry.fill",
        "stylers": [{ "color": "#FFFFFF" }, { "visibility": "on" }]
      },
      {
        "featureType": "road",
        "elementType": "geometry.stroke",
        "stylers": [{ "color": "#EDEDED" }, { "visibility": "on" }]
      },
      {
        "featureType": "transit.station",
        "stylers": [{ "visibility": "off" }]
      },
      {
        "featureType": "transit.line",
        "elementType": "labels.text.fill",
        "stylers": [{ "color": "#858585" }, { "visibility": "on" }]
      },
      {
        "featureType": "transit.line",
        "elementType": "geometry.fill",
        "stylers": [{ "color": "#F7F7F7" }, { "visibility": "on" }]
      }
    ]
})}
```
</div></details>


### スタイルの概要
以下は、特定の地図要素の表示をカスタマイズするために使用したスタイルの一部です。全体のスタイル配列はかなり長くなりますが、ここでは各スタイルが何を行うのか、その意図を簡単に説明します。

#### 水面（Water）
```javascript:script.js
{
  "featureType": "water",
  "stylers": [{ "color": "#E0EDF5" }, { "visibility": "on" }]
}
```
色を淡い青色 `#E0EDF5` に設定し、水面が明確に表示されるようにしています。

#### 人工的な景観（Landscape.man_made）
```javascript:script.js
{
  "featureType": "landscape.man_made",
  "elementType": "geometry.fill",
  "stylers": [{ "color": "#F7F7F7" }, { "visibility": "on" }]
}
```
ジオメトリの塗りつぶしに薄い灰色 `#F7F7F7` を使用し、都市部の建造物などを目立たなくしています。

#### 自然の景観（Landscape.natural）
```javascript:script.js
{
  "featureType": "landscape.natural",
  "stylers": [{ "color": "#F7F7F7" }, { "visibility": "on" }]
}
```
自然の土地も人工的な景観と同様に薄い灰色 `#F7F7F7` で塗りつぶし、自然の特徴を控えめに表示しています。

#### 行政区分（Administrative.province）
```javascript:script.js
{
  "featureType": "administrative.province",
  "elementType": "geometry.stroke",
  "stylers": [{ "color": "#5F6368" }, { "visibility": "on" }]
},
```
行政区分の境界線の色を暗い灰色 `#5F6368` に設定し、それらが目立つようにしています。

#### 地方行政区域（Administrative.locality）
```javascript:script.js
{
  "featureType": "administrative.locality",
  "elementType": "labels",
  "stylers": [{ "visibility": "on" }]
},
{
  "featureType": "administrative.locality",
  "elementType": "labels.text.fill",
  "stylers": [{ "color": "#858585" }, { "visibility": "on" }]
}
```
ラベルに対する設定で、地方行政区域の名前が表示されるようにしています。
テキストの塗りつぶしには灰色 `#858585`を使用し、読みやすいが目立たない色にしています。

#### 興味のあるポイント（Points Of Interest - POI）
```javascript:script.js
{
  "featureType": "poi",
  "stylers": [{ "visibility": "off" }]
}
```
POIは、ユーザーが地図上で見つけることができる興味深い場所です。これには、店舗、学校、政府の建物などが含まれます。しかし、特定の用途では、これらのデフォルトのマーカーが邪魔になることがあります。上記のスタイルはすべてのPOIの表示をオフにし、地図上でこれらの要素を隠します。

#### 公園（POI.Park）
```javascript:script.js
{
  "featureType": "poi.park",
  "elementType": "labels",
  "stylers": [{ "visibility": "off" }]
}
```
公園もPOIの一種ですが、特に公園のラベル（名前など）を表示しないように設定することができます。これにより、マップ上で自然の緑地を示すために公園が使用されている場合でも、それらのラベルが邪魔になるのを防ぐことができます。

#### 道路（Road）
```javascript:script.js
{
  "featureType": "road",
  "elementType": "labels",
  "stylers": [{ "visibility": "off" }]
}
```
この設定はすべての道路のラベルを非表示にします。ラベルとは、道路の名前や番号など、道路に関するテキスト情報です。これを非表示にすると、地図が読みやすくなり、他の重要な要素にユーザーの注意を集中させることができます。

#### 幹線道路（Road.arterial）
```javascript:script.js
{
  "featureType": "road.arterial",
  "elementType": "labels",
  "stylers": [{ "visibility": "off" }]
}
```
幹線道路は、主要な道路ネットワークであり、より大きな道路や高速道路へとつながる重要な路です。このスタイルでは、これらの道路のラベルを非表示にし、地図上のクラッターを減らしています。

#### 高速道路（Road.highways）
```javascript:script.js
{
  "featureType": "road.highway",
  "elementType": "labels",
  "stylers": [{ "visibility": "off" }]
}
```
高速道路のラベルも非表示にすることで、道路そのものに集中できるようにし、特に都市部の地図では視覚的な混雑を軽減します。

#### 高速道路（制限付きアクセス）（Road.highway.controlled_access）
```javascript:script.js
{
  "featureType": "road.highway.controlled_access",
  "elementType": "labels",
  "stylers": [{ "visibility": "off" }]
}
```
制限付きアクセスのある高速道路、つまりインターチェンジや出入り口が制限されている高速道路のラベルを非表示にすることで、これらの区間での視覚的なシンプリシティを維持します。

#### 地元の道路（Road.local）
```javascript:script.js
{
  "featureType": "road.local",
  "stylers": [{ "color": "#FFFFFF" }, { "visibility": "on" }]
}
```
地元の道路は一般的に小さな街路やアクセス道です。これらは白色`#FFFFFF`にして、シンプルながらも道路が識別しやすいようにしています。

#### 道路の塗りつぶしと境界線（geometry.fill and geometry.stroke）
```javascript:script.js
{
  "featureType": "road",
  "elementType": "geometry.fill",
  "stylers": [{ "color": "#FFFFFF" }, { "visibility": "on" }]
},
{
  "featureType": "road",
  "elementType": "geometry.stroke",
  "stylers": [{ "color": "#EDEDED" }, { "visibility": "on" }]
}
```
道路の塗りつぶしを白`#FFFFFF`で行い、境界線を薄い灰色`#EDEDED`で表示することで、道路のレイアウトを強調しますが、他の地図要素よりも目立たないようにしています。

これらのスタイルを組み合わせることで、地図上の道路がよりシンプルで洗練されたデザインとなり、ユーザーインターフェイスに合わせてカスタマイズされます。また、不必要な情報を隠すことで、特に交通状況やナビゲーションに重点を置いたアプリケーションで、ユーザーが必要な情報に素早くアクセスできるようになります。

#### 交通機関の駅（transit.station）
```javascript:script.js
{
  "featureType": "transit.station",
  "stylers": [{ "visibility": "off" }]
}
```
「交通機関の駅（transit.station）」は、バス停、鉄道駅、地下鉄駅などの公共交通の停留所に対応しています。この設定では、そのような駅のマーカーやラベルの表示を`off`にすることで、地図上から駅の情報を隠します。これは、駅の情報がプロジェクトの目的にとって重要ではない場合や、よりシンプルな地図デザインを求める場合に役立ちます。

#### 交通路線（transit.line）
```javascript:script.js
{
  "featureType": "transit.line",
  "elementType": "labels.text.fill",
  "stylers": [{ "color": "#858585" }, { "visibility": "on" }]
},
{
  "featureType": "transit.line",
  "elementType": "geometry.fill",
  "stylers": [{ "color": "#F7F7F7" }, { "visibility": "on" }]
}
```

一方で、「交通路線（transit.line）」は、バスや鉄道などの交通路線を表す地図上の要素です。ここでの設定では、ラベルのテキストの色を灰色 `#858585` にし、可視性を `on` にして、ルートが識別しやすいようにしながらも、他の要素に比べて目立たないようにしています。さらに、路線のジオメトリ（実際のルートを表す線や形）の塗りつぶしにも薄い灰色 `#F7F7F7` を使用し、存在は明示しつつも全体のデザインに溶け込むようにしています。

## まとめ

この記事では、Google Maps APIを活用して、見た目にも洗練されたカスタムマップの作成手順についてガイドしました。JavaScriptを用いたマップの初期設定、細かなスタイリングのカスタマイズ、さらにはユーザーの操作に応じたインタラクティブな機能の実装方法に至るまでを、わかりやすく段階的に説明しました。これにより、開発者は自らのウェブサイトやアプリケーションに、ユーザーフレンドリーで情報を効果的に伝えるマップを組み込むことができるようになるでしょう。地図情報を利用したサービスを提供する際に、この記事が一助となれば幸いです。