メインコンテンツまでスキップ

React アプリで Mapbox GL JS を使用する

Prerequisite
React とフロントエンド開発の基本的な概念に精通していること。

React は、ユーザーインターフェースを構築するためによく使用される JavaScript ライブラリです。React は DOM を操作するため、DOM を操作し状態を管理する他のライブラリ(例: Mapbox GL JS)と接続するのが混乱しがちです。

このチュートリアルでは、Mapbox GL JS を使用して地図をレンダリングし、地図の中心点の座標とズームレベルを表示し、ユーザーが地図と対話すると表示を更新する React Web アプリを作成する方法を学びます。このチュートリアルで説明する原則を使用して、React と Mapbox GL JS の両方を使用するより複雑なアプリを作成することができます。 このチュートリアルでは、React の HooksClass Components のコードを示します。

はじめに

  • Mapbox アクセストークン。 Mapbox アクセストークンは アカウントページ にあります。
  • Mapbox GL JS。 Mapbox GL JS は、Web 地図を作成するために使用される JavaScript ライブラリです。
  • テキストエディタ。 HTML、CSS、JavaScript を記述するためにテキストエディタを使用します。
  • Node.js と npm。 React アプリをローカルで実行するために必要なコマンドを実行するには、Node.js と npm をインストールします。
  • React に慣れていること。 このチュートリアルを完了するために React の豊富な経験は必要ありませんが、基礎的な概念とワークフローに精通している必要があります。

React アプリの構造を設定する

まず、use-mapbox-gl-js-with-react という新しいフォルダを作成します。

use-mapbox-gl-js-with-react フォルダに新しいファイルを作成します:

  • package.json: このファイルは、React と Mapbox GL JS を含むアプリに必要なすべての Node パッケージを指定するために使用されます。

use-mapbox-gl-js-with-react フォルダに public というフォルダを作成します。 public フォルダに 1 つのファイルを作成します:

  • index.html: この HTML ファイルは、ユーザーが操作できるレンダリングされた Mapbox 地図を表示します。

use-mapbox-gl-js-with-react フォルダに src という別のフォルダを作成します。 src フォルダに 3 つのファイルを作成します:

  • App.js: この JavaScript ファイルは React アプリをセットアップします。
  • index.css: この CSS ファイルは、地図とサイドバーを正しくフォーマットするためのスタイルを含みます。
  • index.js: この JavaScript ファイルは、ブラウザに Mapbox 地図をレンダリングします。

これらのフォルダとファイルを作成すると、次のようなファイル構造になります:

folder use-mapbox-gl-js-with-react

code

package.json

folder public

code index.html

folder src

code App.js

code index.css

code index.js

次のコードを package.json にコピーします:

package.json
{
"name": "use-mapbox-gl-js-with-react",
"version": "0.1.0",
"private": true,
"dependencies": {
"mapbox-gl": "^3.3.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "^4.0.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build"
},
"eslintConfig": {
"extends": [
"react-app"
]
},
"browserslist": [
"defaults",
"not ie 11"
],
"author": "Mapbox",
"license": "MIT"
}

このファイルは React 特有の Node パッケージ reactreact-dom 以外にも、アプリをビルドするために使用される react-scripts(Create React App とも呼ばれます)と、Mapbox GL JS にアクセスするための mapbox-gl を必要とします。

変更を保存します。

コマンドラインで use-mapbox-gl-js-with-react フォルダに移動し、そのフォルダで npm install コマンドを実行します。これにより、package.json ファイルに指定されたすべての Node パッケージがインストールされます。このステップでは package-lock.json ファイルも作成されます。

HTML ページの作成

public/index.html ファイルを開き、次のコードを貼り付けます:

public/index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
name="description"
content="Create a React web app that uses Mapbox GL JS to render a map"
/>
<title>Use Mapbox GL JS in a React app</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

このコードは、ユーザーが見る HTML ページの構造を作成します。ページの <body> には root ID を持つ <div> 要素があります。この <div> は、React アプリがページにレンダリングされるコンテナです。

変更を保存します。

React アプリの作成

src/index.js ファイルを開きます。次のコードを追加して、2 つのスタイルシートと作成する Mapbox GL JS 地図をインポートします:

src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import 'mapbox-gl/dist/mapbox-gl.css';
import './index.css';
import App from './App';

ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);

最初のスタイルシートは、地図を表示するための Mapbox GL JS のスタイルを含みます。2 番目のスタイルシートは、先ほど作成した index.css ファイルです。ここにアプリ固有の CSS を追加します。

Mapbox GL JS を追加する

src/App.js ファイルを開きます。ファイルの先頭に次のインポート文を追加します:

src/App.js
import React, { useRef, useEffect, useState } from 'react';

次に、Mapbox GL をインポートし、アクセストークンを追加します。Create React App を使用するには、Mapbox GL をトランスパイルから除外するための感嘆符を追加し、 eslint ルール import/no-webpack-loader-syntax を無効にする必要があります。accessToken プロパティ を Mapbox アクセストークンの値に設定します:

src/App.js
import mapboxgl from '!mapbox-gl'; // eslint-disable-line import/no-webpack-loader-syntax

mapboxgl.accessToken = 'MAPBOX_ACCESS_TOKEN';

React アプリをセットアップできます!次のコードを App.js の下部に追加して、その後の手順で使用する構造を作成します:

src/App.js
export default function App() {
}

変更を保存します。

アプリのデフォルト状態を設定する

次に、アプリが初期の緯度、経度、ズームレベルを使用するデフォルト値を作成します。 App の内部に次のコードを追加します:

src/App.js
  const mapContainer = useRef(null);
const map = useRef(null);
const [lng, setLng] = useState(-70.9);
const [lat, setLat] = useState(42.35);
const [zoom, setZoom] = useState(9);

状態は地図の経度、緯度、ズームレベルを保存します。これらの値はユーザーが地図と対話するたびに変更されます。

次に、地図を初期化します。このコードは、アプリが HTML ページの DOM ツリーに挿入された直後に呼び出されます。

src/App.js
  useEffect(() => {
if (map.current) return; // initialize map only once
map.current = new mapboxgl.Map({
container: mapContainer.current,
style: 'mapbox://styles/mapbox/streets-v12',
center: [lng, lat],
zoom: zoom
});
});

Mapbox 地図は、React Effect フック またはクラスを使用している場合の componentDidMount() ライフサイクル メソッド内で初期化されます。ここで地図を初期化すると、React が地図を含む要素を作成する前に Mapbox GL JS が地図をレンダリングしようとすることがないようにします。地図の初期化の中で次のオプションも設定します:

  • container オプションは、Mapbox GL JS に特定の DOM 要素内に地図をレンダリングするよう指示します。ここで、アプリは mapContainer useRef または ref を想定しています。クラスコンポーネントを使用している場合は後で HTML 要素に ref を割り当て、その要素が地図コンテナとして機能します。
  • style オプションは地図が使用するスタイルを定義します (mapbox://styles/mapbox/streets-v12)。
  • center および zoom オプションは、状態に保存されている lnglatzoom の値を使用して地図の中心座標とズームレベルを設定します。
  • フックを使用している場合は、map useRef を作成して地図を初期化します。ref はユーザーが地図を操作したときに地図が再ロードされないようにします。

変更を保存します。

地図をレンダリングする

次に、アプリで地図をレンダリングする必要があります。React アプリで Mapbox 地図を初期化するエントリポイントは、return ステートメントで提供される単一の要素です。次のコードを App の閉じ中括弧の上に追加します:

src/App.js
  return (
<div>
<div ref={mapContainer} className="map-container" />
</div>
);

mapContainer ref は、App を新しい <div> 要素にレンダリングすべきということを示します。

地図が正しくレンダリングされるためには、いくつかのスタイルルールが必要です。次のコードを index.css ファイルに追加します:

 
.map-container {
 
height: 400px;
 
}

変更を保存します。コマンドラインで npm start コマンドを実行します。これによりローカルサーバーが起動し、新しい Mapbox 地図が含まれたページがブラウザに表示されます。

ブラウザの開発者コンソールを開くと、no-unused-vars 警告が表示される場合があります。心配ありません これは次のステップでこれらの変数を使用するためです。

新しい座標を保存する

次に、ユーザーが地図と対話した際に取得した新しい緯度、経度、ズームレベルを保存する関数を作成する必要があります。ユーザーが地図を移動したときに状態をこれらの新しい値に設定する Mapbox GL JS の map.on('move') 関数を作成します。フックを使用している場合は、以前の useEffect を使用し、次のコードを地図の初期化の下に追加します。クラスを使用している場合は、次のコードを componentDidMount() 内に追加します:

src/App.js
    map.current.on('move', () => {
setLng(map.current.getCenter().lng.toFixed(4));
setLat(map.current.getCenter().lat.toFixed(4));
setZoom(map.current.getZoom().toFixed(2));
});

この関数はフックを使用している場合は useState()、クラスを使用している場合はsetState() を使用して、地図が移動した際に lnglatzoom の値をリセットします。 また、次のメソッドを使用します。

  • getCenter() は Mapbox GL JS メソッドで、地図の中心にあるポイントの新しい経度と緯度を取得します。
  • getZoom() は地図の現在のズームレベルを判断するための Mapbox GL JS メソッドです。
  • toFixed() は JavaScript メソッドで、結果の浮動小数点数を指定した桁数に丸めます。

座標を表示する

これで、この情報を収集して保存できるようになったため、return を使用して地図に表示できます。作成した地図を保持する <div> の開始タグの内部に、新しい <div> を追加して地図の経度、緯度、およびズームレベルを表示します。return ステートメントは次のようになります:

src/App.js
  return (
<div>
<div className="sidebar">
Longitude: {lng} | Latitude: {lat} | Zoom: {zoom}
</div>
<div ref={mapContainer} className="map-container" />
</div>
);

サイドバーを正しくページに表示するには、いくつかのスタイルルールが必要です。次のCSSをindex.cssファイルに追加してください。

 
.sidebar {
 
background-color: rgb(35 55 75 / 90%);
 
color: #fff;
 
padding: 6px 12px;
 
font-family: monospace;
 
z-index: 1;
 
position: absolute;
 
top: 0;
 
left: 0;
 
margin: 12px;
 
border-radius: 4px;
 
}

変更を保存し、ブラウザページに戻ります。今では上部左隅にサイドバーがあり、index.css で設定した CSS ルールに従って表示されます。サイドバーには地図の現在の経度と緯度、ズームレベルが表示されます。地図をズームインおよびズームアウトしたりパンしたりすると、サイドバーの内容が更新されます。

完成品

Mapbox GL JS を使用して地図をレンダリングし、地図の中心座標とズームレベルを表示し、ユーザーが地図と対話したときにその表示を更新する React アプリが完成しました。

最終的な index.html ページは次のようになります:

public/index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
name="description"
content="Create a React web app that uses Mapbox GL JS to render a map"
/>
<title>Use Mapbox GL JS in a React app</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

最終的な index.js ファイルは次のようになります:

src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import 'mapbox-gl/dist/mapbox-gl.css';
import './index.css';
import App from './App';

ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);

最終的な App.js ファイルは次のようになります:

src/App.js
import React, { useRef, useEffect, useState } from 'react';
import mapboxgl from '!mapbox-gl'; // eslint-disable-line import/no-webpack-loader-syntax

mapboxgl.accessToken = 'MAPBOX_ACCESS_TOKEN';

export default function App() {
const mapContainer = useRef(null);
const map = useRef(null);
const [lng, setLng] = useState(-70.9);
const [lat, setLat] = useState(42.35);
const [zoom, setZoom] = useState(9);

useEffect(() => {
if (map.current) return; // initialize map only once
map.current = new mapboxgl.Map({
container: mapContainer.current,
style: 'mapbox://styles/mapbox/streets-v12',
center: [lng, lat],
zoom: zoom
});

map.current.on('move', () => {
setLng(map.current.getCenter().lng.toFixed(4));
setLat(map.current.getCenter().lat.toFixed(4));
setZoom(map.current.getZoom().toFixed(2));
});
});

return (
<div>
<div className="sidebar">
Longitude: {lng} | Latitude: {lat} | Zoom: {zoom}
</div>
<div ref={mapContainer} className="map-container" />
</div>
);
}

最終的な index.css ファイルは次のようになります:

src/index.css
.map-container {
height: 400px;
}

.sidebar {
background-color: rgb(35 55 75 / 90%);
color: #fff;
padding: 6px 12px;
font-family: monospace;
z-index: 1;
position: absolute;
top: 0;
left: 0;
margin: 12px;
border-radius: 4px;
}

次のステップ

Mapbox GL JS を使用する React アプリを作成したので、Mapbox React examples GitHub リポジトリで他のより複雑な例を探索できます。

この{Type}は役に立ちましたか?