Web アプリケーションは地図を組み込むことで大きな恩恵を受け、ユーザーに貴重な位置ベースの情報を提供します。地図は、見知らぬ場所への移動から近くの飲食店の発見まで、私たちの世界との関わりを変えてきました。その結果、最近では地図を Web サイトに統合することがますます一般的になってきています。それにもかかわらず、機能的かつユーザーフレンドリーな地図を設計することは、特にこの分野の経験が不足している人にとっては困難を伴う可能性があります。この記事では、ブラウザ内で効果的なマップを作成する方法に関する役立つヒントを紹介します。 技術スタック テクノロジーについて話し合いましょう。マップを操作するときは、通常、次の 3 つのレイヤーを使用します。 ボタンやフォームを含むユーザー インターフェイスをレンダリングします。私たちのスタックでは、React がこの役割を果たします。 マップをレンダリングし、ユーザー操作を可能にします。これには Mapbox を使用します。 マーカーやポリゴンに関する情報などのデータをサーバーから取得します。データを取得するには、ブラウザの組み込みフェッチ機能を使用します。 マップを操作する際のテクノロジー スタックをより深く理解するために、各項目を確認してみましょう。 反応する の ライブラリを使用すると、ページ要素を便利かつ効率的に操作できるようになります。これは Facebook が独自に使用するために開発したもので、ページ上のボタン、フォーム、その他のインタラクティブな要素などの多数のコンポーネントが含まれています。たとえば、Facebook が作成したのは、 さまざまな状態をすばやく比較します。 反応する 調整アルゴリズム ページ上の要素の変更はブラウザにとって最も負荷の高い操作であるため、可能な限り効率的に実行することが重要です。この問題に対処するために、Facebook のエンジニアは、ページ上の要素を迅速かつ簡単に変更できる React ライブラリを開発しました。 React では、ページ上で迅速な状態変更を提供するだけでなく、DOM 要素を直接操作せずにこれを宣言的に行うことができます。代わりに、通常は抽象化を使用します。 HTML のように見えます。例を考えてみましょう。 JSX // It's our state. Is the user our friend or not? // false by default const [isFriend, setIsFriend] = useState(false) // Depending on the state, we show the text on the button const buttonText = isFriend ? 'Your my Friend' : 'Add as Friend' // There is JSX, syntax for UI // In this case, we display a button, when clicked, we change the state return ( <button onClick={() => setIsFriend(true)}>{buttonText}</button> ) フォーム、ボタン、入力などの通常の DOM 要素を含むコンポーネントを階層の最下位にネストすることができます。これらの単純な要素を組み立てることにより、完全なフォームなどのより複雑な要素を作成できます。 const Form = () => ( <form> <input name="Email"/> <input name="Password"/> </form> ) const App = () => ( <main> <h1>My form!</h1> <Form /> </main> ) React はマップのコンテキストでどのように私たちを支援しますか?ページ上の地図はボタンやフォームと同様にインタラクティブであるため、地図上のクリックなどのイベントを通じてレンダリングとインタラクションを最適化することを目指しています。 React は、この最適化の実現に役立ちます。以下にその仕組みの例を示します。 // Use React to render the map with different event handlers // and render markers return ( <BaseMap onInitMap={() => console.log('I am alive!')} onClickMap={() => console.log('Click!')} onDestroyMap={() => console.log('Oh no!')} > <ClustersMarkers /> <PostsMarkers /> <ListingsMarkers /> </BaseMap> ) React を使用する場合、ページ上の要素の効率的な操作、素早い変更、イベントを介した要素との対話が可能であることを覚えておくことが重要です。これは HTML に似た抽象化によって実現され、単純なコンポーネントから複雑なコンポーネントを簡単に作成できるようになります。 マップボックス さて、マップ自体について説明しましょう。マップの作成と使用は困難な場合があり、マップをゼロからデザインできる企業はほんのわずかです。通常、ほとんどの人は、試行されテストされたユーザーフレンドリーな API を備えた既製のライブラリに依存しています。 Google Maps、Leaflet、Bing Maps、Mapbox など、多数の動的マップ プロバイダーが利用可能です。ただし、次の点に焦点を当てます。 その広範な機能と公正な価格設定ポリシーにより、たとえば、Google マップの料金 Mapbox は料金のみを請求しますが、1 か月あたり 100,000 のマップビューの場合 。さらに、Mapbox では、1 か月あたり最大 50,000 の地図ビューに無料でアクセスできます。 マップボックス 700ドル 250ドル マップボックスのオファー 、地図用の Photoshop とよく比較されるツールです。このツールを使用すると、デザイナーはカスタム スタイルを作成したり、不要なマップ要素を非表示にしたり、家の表示を削除したりできます。その利点の 1 つは、可視性を向上できることです。 。もう 1 つの利点は、コーポレート カラーの地図スタイルを試す機会があることです。ただし、ユーザー エクスペリエンスを考慮し、緑の草や青い水などの見慣れたカラー パレットを維持することが重要です。 Mapbox Studio の最も優れた点は、要件の開発と転送の必要性を排除することで地図設計プロセスを簡素化し、最終的に地図の操作コストを削減できることです。 マップボックススタジオ 興味がある点 さらに、Mapbox は 住所を座標に変換したり、その逆に変換したりできるため、地図上の点を見つけるプロセスが簡素化されます。ただし、ツールの 不十分な場合があり、特定のプロジェクトで困難が生じる可能性があります。 Mapbox がデータを収集する場所 、政府、OpenStreetMap などのオープン データ イニシアチブ、民間企業など。 ジオコーディングツール 世界中でカバー 多数の情報源 Mapbox はさまざまな機能を提供します ですが、 何らかの改善が得られる可能性があります。たとえば、マーカー機能を組み込む場合、ドキュメントよりも例の方が有益な場合があります。さらに、マーカー クラスター、カスタム データの読み込み、正規化、マーカーの状態の変更など、複数のコンポーネントをマージするときに問題が発生する可能性があります。 実践例 ドキュメンテーション Mapbox マップをもう一度見てみましょう。は何ですか する? マップボックス API ページ上の HTML 要素内のマップを初期化します。 マップを構成する画像をロードしてレンダリングします。 GeoJson を入力データとして使用して、マーカーなどの追加要素を描画します。 クリックやズームの変更など、処理可能なイベントを生成します。 これらの各項目を詳しく見てみましょう。 Mapbox はタイルを使用した地図レンダリングに特化しています。タイルは、大きなマップを構成する小さな正方形の画像です。タイルのデフォルトのサイズは 512x512 ピクセルで、次のいずれかになります。 。 タイルは、道路、建物、名所 (PoI) などを表示するために使用されます。これらは動的にスタイル設定でき、軽量で、マップとのスムーズな操作が可能です。 一方、タイルは衛星画像を表示するために使用されます。 ベクターまたはラスター ベクター ラスター ご存知のとおり、Mapbox Studio では、マップ タイルに含めたい特定のデータを選択できます。これらのタイルは次に、 これは、Web 上に画像やその他のグラフィック要素を表示するブラウザーの特別な DOM 要素です。イメージとしては、Google ドキュメントのキャンバスにドキュメントが表示される方法と似ています。 キャンバス <canvas width="100" height="100" /> Mapbox はタイルの読み込み、挿入、更新を処理します。必要なのは、地図を表示する場所と、ズーム レベルや地図の座標などの初期条件を指定することだけです。 Mapbox を使用するには、 、これは Mapbox アカウントで見つかる一意のキーです。基本的なマップを設定するための簡単な例を次に示しますが、詳細については、 提供された: アクセストークン リンク mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN'; const map = new mapboxgl.Map({ container: 'map', // we can use an Id or an element style: 'mapbox://styles/mapbox/streets-v11', // URL for styles center: [-74.5, 40], // initial coordinates [lng, lat] zoom: 9, // initial zoom }); この後、ID が「map」の要素でページ上の地図を取得します。 ユーザーに地図上でより多くの情報を提供するために、特定の施設の位置や特定のエリアの境界を表示することがよくあります。これを実現するために、と呼ばれる特定のデータ形式を使用します。 そして、このデータを紹介する方法を Mapbox に指示します。 地理JSON GeoJSON は、地図上に地理構造を保存するための標準形式です。住所、場所、道路、高速道路、国境、国、州、およびマルチパートとして知られるこれらの組み合わせなどの地理的オブジェクトを記述するさまざまなプリミティブ タイプを格納できます。 GeoJSON は 2008 年に導入され、次のように表されます。 { "type": "Feature", // also can be FeatureCollection, it's collection of Feature "geometry": { "type": "Point", // also can be LineString, Polygon, MultiPolygon "coordinates": [125.6, 10.1] // for other types you can use Array with coordinates }, "properties": { // it's metadata, we can you that to show something on the map "name": "Dinagat Islands" } } Mapbox で使用される座標系について話しましょう。デフォルトでは、Mapbox は 、これは地球を平らな面に投影してタイルを操作する方法です。これは Web メルカトルとして知られ、オンライン マップの標準です。ただし、マーカーとポリゴンに関するデータを処理する場合は、と呼ばれる別の座標系が使用されます。 。このシステムは、緯度と経度に基づいて地球の楕円体上の座標を記述します。 Mapbox およびその他の地図プロバイダーは、座標を EPSG 4326 から EPSG 3857 に自動的に変換します。 では、 メソッドを使用できます。 EPSG 3857 EPSG 4326 投影 map.setProjection 次に、地図上に GeoJSON を表示する方法について説明します。 Mapbox は、役立つ 2 つのエンティティを提供します。 — これがデータシードです。 GeoJSON データを使用して新しいソースを作成し、たとえば、フィーチャ コレクション内の各フィーチャの ID を生成するように構成できます。 ソース — これはデータ表現です。ソースからのデータは、境界を表示するなど、さまざまな方法で表示できます。 層 地図上にポリゴンやマーカーを表示するには、サーバーから GeoJson 形式のデータを取得する必要があります。次に、ソースを作成し、そこにデータを入力し、必要なレイヤーに接続します。 const geoJsonFeature = { 'type': 'Feature', 'geometry': { 'type': 'Polygon', 'coordinates': [ [-67.13734, 45.13745], [-66.96466, 44.8097], [-68.03252, 44.3252], [-67.13734, 45.13745] ] } } // Create source with our data map.addSource('ourSource', { 'type': 'geojson', 'data': geoJsonFeature }); // Add layer for background map.addLayer({ 'id': 'background', 'type': 'fill', 'source': 'ourSource', // название нашего source 'layout': {}, 'paint': { 'fill-color': '#0080ff', 'fill-opacity': 0.5 } }); // Add layer for border map.addLayer({ 'id': 'border', 'type': 'line', 'source': 'ourSource', 'layout': {}, 'paint': { 'line-color': '#000', 'line-width': 3 } }); このコードを実行すると、次の結果が得られます。 このトピックについて詳しくは、以下を参照してください。 マップボックスから提供されています。このチュートリアルでは、マップを初期化してデータを表示するプロセスについて説明しました。次に、クリック、ドラッグ、ズームなどのイベントを処理する方法を検討します。たとえば、Mapbox を使用してイベントを監視し、ユーザーがマップ上でカーソルを移動すると、コンソールに座標を表示できます。これを実現するには、DOM 要素の操作と同様に、必要なイベント タイプを指定して メソッドを呼び出すだけです。 ドキュメンテーション on map.on('mousemove', (e) => { console.log(JSON.stringify(e.point)); }); // Result: {"x":330,"y":49} 要約すると、何を覚えておく必要があるでしょうか? Mapbox を使用すると、地図を表示し、その上にデータを描画し、地図イベントを処理できます。同時に、Mapbox は画像 (タイル) の読み込みと表示を処理します。 フェッチ について一言 。マップ上にデータをレンダリングする方法はすでに説明しましたが、まずサーバーからデータを取得する必要があります。ページをリロードせずにバックグラウンドでサーバーから動的にデータをリクエストする場合、このアプローチを「アプローチ」と呼びます。 (「 ML」)。 Axios や XMLHttpRequest (ネイティブ) など、サーバーからデータを非同期にロードするためのツールは数多くあります。 フェッチ アヤックス 同期 JavaScript と X 何を覚えるべきですか?サーバーからデータを取得します。これには多くのライブラリがありますが、ここでは fetch を使用します。次に、ニュアンスがあるため、マップを操作するときにこれを具体的にどのように行うかを見ていきます。 反応 + マップボックス ここで、上記のテクノロジーがどのように連携して機能するかを見てみましょう。まず、ポリゴンを表示するためのデータを fetch で取得します。次に、マップの初期化を宣言し、ロード後にマップにポリゴンを追加します。 実際の例は次の場所にもあります。 提供された。 リンク const useFetch = () => { /* Our data { 'type': 'Feature', 'geometry': { 'type': 'Polygon', 'coordinates': [ [ [-67.13734, 45.13745], [-68.03252, 44.3252], [-68.90478, 47.18479], [-67.13734, 45.13745], ] ] } } */ const [data, setData] = useState(null) useEffect(() => { fetch('https://our-api.com/polygon') .then(response => response.json()) .then(setData) .catch(e => { console.error(e) }) }, [setData]) return { data } } const BaseMap = () => { // Use the hook to fetch data const { data } = useFetch(GET_REGION); // Map instance const map = useRef(null); // DOM element const mapContainer = useRef(null); // Main logic - init the map and add the event useEffect(() => { if (map.current) { return; // initialize map only once } mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN'; map.current = new mapboxgl.Map({ container: mapContainer.current, style: 'mapbox://styles/mapbox/light-v10', // style URL (it's Mapbox's core style) center: [-68.137343, 45.137451], // starting position zoom: 5 // starting zoom }); // Handle event map.on('load', () => { const sourceId = 'source-region' // Add a data source containing GeoJSON data map.addSource(sourceId, { 'type': 'geojson', 'data': data.region // our data from Apollo }); // Add a new layer to visualize the polygon map.addLayer({ 'id': 'background', 'type': 'fill', 'source': sourceId, // reference the data source 'paint': { 'fill-color': '#0080ff', // blue color fill 'fill-opacity': 0.5 } }); // Add a black outline around the polygon map.addLayer({ 'id': 'outline', 'type': 'line', 'source': sourceId, 'paint': { 'line-color': '#000', 'line-width': 3 } }); }); }); return <div ref={mapContainer} />; } 結論 私たちは、将来のアーキテクチャを支えるテクノロジー スタックに注目しました。次の記事では、マップ アーキテクチャの設計に役立つ原則、モジュールの結合度を最大限に低くし、凝集度を高める方法、およびスケーラブルなマップ システムを維持および開発する方法について説明します。 ご清聴ありがとうございました!すてきな一日を。