Web アプリケーションは地図を組み込むことで大きな恩恵を受け、ユーザーに貴重な位置ベースの情報を提供します。地図は、見知らぬ場所への移動から近くの飲食店の発見まで、私たちの世界との関わりを変えてきました。その結果、最近では地図を Web サイトに統合することがますます一般的になってきています。それにもかかわらず、機能的かつユーザーフレンドリーな地図を設計することは、特にこの分野の経験が不足している人にとっては困難を伴う可能性があります。この記事では、ブラウザ内で効果的なマップを作成する方法に関する役立つヒントを紹介します。
テクノロジーについて話し合いましょう。マップを操作するときは、通常、次の 3 つのレイヤーを使用します。
ボタンやフォームを含むユーザー インターフェイスをレンダリングします。私たちのスタックでは、React がこの役割を果たします。
マップをレンダリングし、ユーザー操作を可能にします。これには Mapbox を使用します。
マーカーやポリゴンに関する情報などのデータをサーバーから取得します。データを取得するには、ブラウザの組み込みフェッチ機能を使用します。
マップを操作する際のテクノロジー スタックをより深く理解するために、各項目を確認してみましょう。
の
ページ上の要素の変更はブラウザにとって最も負荷の高い操作であるため、可能な限り効率的に実行することが重要です。この問題に対処するために、Facebook のエンジニアは、ページ上の要素を迅速かつ簡単に変更できる React ライブラリを開発しました。 React では、ページ上で迅速な状態変更を提供するだけでなく、DOM 要素を直接操作せずにこれを宣言的に行うことができます。代わりに、通常は抽象化を使用します。
// 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 など、多数の動的マップ プロバイダーが利用可能です。ただし、次の点に焦点を当てます。
マップボックスのオファー
さらに、Mapbox は
Mapbox はさまざまな機能を提供します
Mapbox マップをもう一度見てみましょう。は何ですか
ページ上の HTML 要素内のマップを初期化します。
マップを構成する画像をロードしてレンダリングします。
GeoJson を入力データとして使用して、マーカーなどの追加要素を描画します。
クリックやズームの変更など、処理可能なイベントを生成します。
これらの各項目を詳しく見てみましょう。
Mapbox はタイルを使用した地図レンダリングに特化しています。タイルは、大きなマップを構成する小さな正方形の画像です。タイルのデフォルトのサイズは 512x512 ピクセルで、次のいずれかになります。
ご存知のとおり、Mapbox Studio では、マップ タイルに含めたい特定のデータを選択できます。これらのタイルは次に、
<canvas width="100" height="100" />
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」の要素でページ上の地図を取得します。
ユーザーに地図上でより多くの情報を提供するために、特定の施設の位置や特定のエリアの境界を表示することがよくあります。これを実現するために、と呼ばれる特定のデータ形式を使用します。
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 はmap.setProjection
メソッドを使用できます。
次に、地図上に GeoJSON を表示する方法について説明します。 Mapbox は、役立つ 2 つのエンティティを提供します。
地図上にポリゴンやマーカーを表示するには、サーバーから 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 } });
このコードを実行すると、次の結果が得られます。
このトピックについて詳しくは、以下を参照してください。on
メソッドを呼び出すだけです。
map.on('mousemove', (e) => { console.log(JSON.stringify(e.point)); }); // Result: {"x":330,"y":49}
要約すると、何を覚えておく必要があるでしょうか? Mapbox を使用すると、地図を表示し、その上にデータを描画し、地図イベントを処理できます。同時に、Mapbox は画像 (タイル) の読み込みと表示を処理します。
について一言
何を覚えるべきですか?サーバーからデータを取得します。これには多くのライブラリがありますが、ここでは 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} />; }
私たちは、将来のアーキテクチャを支えるテクノロジー スタックに注目しました。次の記事では、マップ アーキテクチャの設計に役立つ原則、モジュールの結合度を最大限に低くし、凝集度を高める方法、およびスケーラブルなマップ システムを維持および開発する方法について説明します。
ご清聴ありがとうございました!すてきな一日を。