REACT を操作しています

Maps API for JavaScript を React の機能コンポーネントと組み合わせることで、シームレスなユーザー体験を提供し、メンテナンスが容易な対話型の Web アプリケーションを作成できます。これは、アプリケーション全体でコンポーネントを再利用してコードの重複を削減できるためです。

マップを特定のビジネスニーズに合わせて適切に調整するには、多くのカスタマイズが必要になります。 マップを React コンポーネントとして構築することで、最も複雑なカスタマイズも 1 つのコンポーネントにカプセル化でき、マップの管理と再利用が容易になります。

チュートリアルの目的

このチュートリアルの目的は、レストランのリストを表示する React アプリケーションを作成し、レストランのエントリをクリックしてその場所を表示し、現在の場所から最速のルートを見つけることができるようにすることです。

このチュートリアルでは、次の React コンポーネントを作成する方法について説明します。

  1. App - メインコンポーネントとして機能し、ブラウザウィンドウで他のすべてのコンポーネントをレンダリングします。
  2. RestaurantList - ユーザーの近隣にあるレストランを一覧表示します。
  3. RestaurantEntry - 一覧表内のレストランのエントリを表します。
  4. Map - Maps API for JavaScript を使用してマップをレンダリングし、ユーザーがレストランのエントリをクリックしたときに最速ルートを計算します。

次の図は、これらの反応コンポーネントを一覧表で示したものです。 Maps API for JavaScript を React と統合して作成された食品配達アプリケーション

このチュートリアルを完了する方法については、次のセクションを参照してください。また、 React 機能コンポーネントを使用して Maps API for JavaScript を使用し、動的でインタラクティブな Web アプリケーションを作成する方法についても理解を深めることができます。

作業を開始する前に

このチュートリアルを完了する前に、次の前提条件を満たしていることを確認してください。

  • HTML 、 CSS 、および JavaScript についての基本的な理解
  • Node.js に精通し、機能的なコンポーネントとフックに反応します
  • さらに、 HERE platform アカウントを取得します

    詳細について は、 HERE 基本プランの価格表を参照してください。

  • 最後に、任意のテキストエディタまたは IDE (Visual Studio コード、サブライムテキスト、 Atom など ) がインストールされていることを確認します。

REACT 環境を設定します

Create React アプリ 環境を使用して、新しい React アプリケーションを設定します。 この環境では、はじめにが単一ページのアプリケーションを迅速に構築できます。

  1. ターミナルウィンドウを開き、新しい REACT プロジェクトを作成するディレクトリに移動します。

  2. create-react-app 次のコマンドを実行して、新しい REACT プロジェクトを開始します。

     npx create-react-app my-food-delivery-app
    

    結果: 上記の呼び出しによって、アプリケーションの起動に必要な足場が作成されます。 my-food-delivery-app ディレクトリ内のディレクトリ構造には、次の構造があり src ます( react コンポーネントはディレクトリに存在します)。

     my-food-delivery-app
     ├── README.md
     ├── node_modules
     ├── package.json
     ├── .gitignore
     ├── public
     │   ├── ...
     └── src
         ├── App.css
         ├── App.js
         ├── App.test.js
         ├── index.css
         ├── index.js
         ├── logo.svg
         └── reportServiceVitals.js
         └── setupTests.js
    
  3. 次のコマンドを実行して、新しく作成したディレクトリにナビゲートします。

     cd my-food-delivery-app
    
  4. グローバル変数に多塗りが使用されないようにアプリを設定します。

    の最新バージョン create-react-app では、 webpack 5 が使用され、グローバル変数にポリフィルを使用するように設定されています。 このデフォルトオプションは、 Maps API for JavaScript と互換性がありません。

    1. 次のコマンドを実行して、アプリを取り出します。

       npm run eject
      
    2. 確認のメッセージが表示されたら Y 、キーを押してイジェクトを確認します。

    3. config ディレクトリから、任意のテキストエディタを使用 webpack.config.js してファイルを開きます。

    4. 次 の例に示すように、module.exportsオブジェクト内にnodeという新しいプロパティを追加し、その値をfalseに設定します。

       module.exports = {
       // Your existing webpack configuration options
      
       node: {
           global: false
        }
       };
      
    5. ファイルを保存します。

  5. maps-api-for-javascript NPM パッケージをインストール :

    1. 次のコマンドを実行して、 NPM 設定にレジストリエントリを追加します。

       npm config set @here:registry https://repo.platform.here.com/artifactory/api/npm/maps-api-for-javascript/
      
    2. @here 次のコマンドを実行して、名前空間から API パッケージをインストールします。

       npm install @here/maps-api-for-javascript
      

      結果: 環境のセットアップが完了し、サンプルアプリケーションのビルドに必要なすべてのパッケージがインストールされます。

  6. 次のコマンドを実行して、環境のセットアップが正常に完了したことを確認します。

     npm start
    

    結果: このコマンド を使用すると、ブラウザの http://localhost:3000 アドレスにある「ホットリロード」機能を使用して開発サーバが起動されます。 さらに、ターミナルに Compiled successfully! メッセージが表示されます。

地図を表示する反応機能コンポーネントを追加します

useRef および useEffect フックを使用して、マップを保持する<div>要素をレンダリングする機能コンポーネントを作成します。 useRef フックによって、 div 要素への参照と、マップインスタンスへの参照が作成されます。 useEffect フックは、マップインスタンスがすでに作成されているかどうかを確認します。 そうでない場合、フックは Maps API for JavaScript を使用して新しいマップを作成し、初期マッププロパティ ( 中央、ズーム レベルなど ) を設定して、マップ参照を設定します。 フックを使用 Behavior すると、地図上でパンおよびズーム機能を有効にするオブジェクトも作成されます。

  1. src ディレクトリに新しい Maps.js ファイルを作成します。

  2. Maps.js ファイルで 、 @here/maps-api-for-javascript パッケージからReactuseEffectuseRef、およびHオブジェクトをインポートします。

     import React, { useEffect, useRef } from 'react';
     import H from '@here/maps-api-for-javascript';
    
  3. Map オブジェクト props を引数として受け取る関数としてコンポーネントを定義します。

     const Map = ( props ) => {
       const mapRef = useRef(null);
       const map = useRef(null);
       const platform = useRef(null)
       const { apikey } = props;
      }
    

    Map この関数は props 、オブジェクトから API キー を抽出し、 2 つの参照を作成します。 1 つはブラウザーでマップをレンダリングするマップ HTML 要素用で、もう 1 つは Maps API for JavaScript マップインスタンス用です。 useRef フックを使用すると、マップのインスタンスが 1 つだけ作成され、コンポーネントの不要な再レンダリングが防止されます。

  4. MapuseEffect の例に示すように、コンポーネント関数内でフックを定義します。

     useEffect(
       () => {
         // Check if the map object has already been created
         if (!map.current) {
           // Create a platform object with the API key
           platform.current = new H.service.Platform({ apikey });
           // Create a new Raster Tile service instance
           const rasterTileService = platform.current.getRasterTileService({
             queryParams: {
               style: "explore.day",
               size: 512,
             },
           });
           // Creates a new instance of the H.service.rasterTile.Provider class
           // The class provides raster tiles for a given tile layer ID and pixel format
           const rasterTileProvider = new H.service.rasterTile.Provider(
             rasterTileService
           );
           // Create a new Tile layer with the Raster Tile provider
           const rasterTileLayer = new H.map.layer.TileLayer(rasterTileProvider);
           // Create a new map instance with the Tile layer, center and zoom level
           const newMap = new H.Map(mapRef.current, rasterTileLayer, {
             pixelRatio: window.devicePixelRatio,
             center: {
               lat: 64.144,
               lng: -21.94,
             },
             zoom: 14,
           });
    
           // Add panning and zooming behavior to the map
           const behavior = new H.mapevents.Behavior(
             new H.mapevents.MapEvents(newMap)
           );
    
           // Set the map object to the reference
           map.current = newMap;
         }
       },
       // Dependencies array
       [apikey]
     );
    
     // Return a div element to hold the map
     return <div style={ { width: "100%", height: "500px" } } ref={mapRef} />;
    

    ここで、

    • useEffect フックは、マップインスタンスが作成されているかどうかを確認します。 そうでない場合、フックは H.Map コンストラクタを使用して、指定されたオプションを使用して新しいオプションを作成します。
    • behavior 変数は H.mapevents.BehaviorH.mapevents.MapEvents クラスおよびクラスを使用して、マップにパンおよびズームの動作を追加します。
    • map.current = NewMap このステートメントは、新しく作成されたマップインスタンスを格納するようにマップ参照を更新します。
    • return ステートメントは 、適切なスタイルの<div>要素と 、ref属性がmapRef参照に設定された要素を返します。
  5. ファイルの最後に Map 、コンポーネントをデフォルトのエクスポートとしてエクスポートします。

     export default Map;
    

    このステートメントは、他のモジュールがこの機能コンポーネントをインポートして他のモジュールと統合できるようにします。

  6. src ディレクトリから App.js ファイルを開きます。

  7. ファイルの既定の内容を次のコードで置き換えます。

     import Map from './Map';
     import React, { useState } from 'react';
    
     const apikey = 'Your API key'
    
     function App() {
       return (
         <div>
           <Map apikey={apikey} />
         </div>
       );
     };
    
     export default App;
    

    このコード は、Mapコンポーネントを含むAppコンポーネントをエクスポートしてレンダリングします。 Map コンポーネントが ./Map ファイルからインポートさ App れ、コンポーネント内にレンダリングされます。 App コンポーネントがレンダリングされると Map 、コンポーネントが表示 <div> されます。コンポーネントは、 Maps API for JavaScript を使用してマップを作成し、要素内にレンダリングします。

  8. ファイルを保存します。

結果: React は、次の例に示すように、マップの機能コンポーネントをレンダリングします。

反応する機能コンポーネント内の基本的なマップ
図 1. 反応する機能コンポーネント内の基本的なマップ

ユーザーとレストランのデータを設定します

ユーザーの現在の場所、およびユーザーの近隣にある複数のサンプルレストランの場所を設定します。

簡単にするために、これらの値は手動で設定され、ランタイム中に変更することはできません。 ただし、リアルタイムの地理位置情報データに基づいて動的に値を設定するようにコードを変更できます。

  1. App.js ファイルで、次の例に示すように、現在のユーザーの場所を設定する変数を作成します。

     // Austurvöllur square in Reykjavik
     const userPosition = { lat: 64.1472, lng: -21.9398 };
    
  2. 同じファイルに、ユーザーの場所に近いレストランの名前と場所を設定するオブジェクトの配列を追加します。

     const restaurantList = [
       {
         name: "The Fish Market",
         location: { lat: 64.1508, lng: -21.9536 },
       },
       {
         name: "Bæjarins Beztu Pylsur",
         location: { lat: 64.1502, lng: -21.9519 },
       },
       {
         name: "Grillmarkadurinn",
         location: { lat: 64.1475, lng: -21.9347 },
       },
       {
         name: "Kol Restaurant",
         location: { lat: 64.1494, lng: -21.9337 },
       },
     ];
    
  3. ファイルを保存します。

React コンポーネントを定義して、レストランのエントリをグリッドで表示します

RestaurantList レストランのエントリを別々のコンポーネントとしてレンダリングするコンポーネントを設定します。

  1. src React プロジェクトフォルダのディレクトリで、という名前のファイルを作成 RestaurantList.jsし、そのファイルを任意のテキストエディタで開きます。

  2. RestaurantList.js ファイルで RestaurantEntry 、次の例に示すように、リスト内のレストランのエントリを表す機能コンポーネントを作成します。

     function RestaurantEntry(props) {
       const handleClick = () => {
         props.onClickHandler(props.data.location);
       };
       // Add basic styling for each restaurant entry
       const entryStyle = {
         display: "inline-block",
         padding: "10px",
         margin: "5px",
         border: "1px solid gray",
         borderRadius: "5px",
         cursor: "pointer",
       };
    
       return (
         <div style={entryStyle} onClick={handleClick}>
           {props.data.name}
         </div>
       );
     }
    

    ここで、

    • props パラメータには、特定のレストランおよび onClickHandler 関数のデータが含まれています。
    • コンポーネントは <div> 、コンテンツとしてレストラン名を持つ要素を返します。
  3. RestaurantList.js ファイルに RestaurantList 、次の例に示すように、レストランのリストを表すという別の機能コンポーネントを追加します。

     function RestaurantList(props) {
       const entries = props.list;
       const list = entries.map((entry) => {
         return <RestaurantEntry data={entry} onClickHandler={props.onClickHandler} key={Math.random()}></RestaurantEntry>
       });
       return (
         <div id="restaurant-list" style={ {'display': 'grid'} } >
         {list}
         </div>
       )
     }
    

    ここで、

    • props このパラメータには list 、レストランのエントリの配列と onClickHandler 関数が含まれています。
    • entries 配列の各entry要素が RestaurantEntry コンポーネントになり 、entryデータがdata prop として渡され、 props のonClickHandler関数が onClickHandlerprop として渡されます。 を使用して、各コンポーネントに一意のキーも割り当て Math.random()られます。
    • コンポーネントは 、id属性がrestaurant-listに設定された<div>要素を返し ます。 コンポーネントは style 、属性を使用して、表示プロパティがに設定されたインライン CSS を適用 gridします。
    • <div> 要素 RestaurantEntry は、コンポーネントを含むリスト変数をレンダリングします。
  4. RestaurantList.js 次の例に示すように、ファイルの最後に export ステートメントを追加します。

     export default RestaurantList;
    

    export このステートメントを使用 RestaurantList すると、他のモジュールまたはファイルでコンポーネントをインポートし、再利用可能なコンポーネントとして使用できます。

  5. 次 の例に示すように、App.jsファイルで、RestaurantListおよびRestaurantEntryコンポーネントをブラウザウィンドウに表示するようにApp機能コンポーネントを更新します。

     function App() {
       const [restaurantPosition, setRestaurantPosition] = useState(null);
    
       const onClickHandler_ = (location) => {
         setRestaurantPosition(location);
       };
    
       return (
         <div>
           <RestaurantList list={restaurantList} onClickHandler={onClickHandler_} />
           <Map
             apikey={apikey}
             userPosition={userPosition}
             restaurantPosition={restaurantPosition}
           />
         </div>
       );
     }
    

    ここで、

    • useState フックによって状態変数restaurantPositionと レストランの位置を更新する関数setRestaurantPositionが作成されます。 の初期値 restaurantPosition はに設定 nullされています。
    • onClickHandler_ この関数は、 restaurantPosition 呼び出されたときに状態変数を更新するコールバック関数です。 この関数は location パラメータを取り restaurantPosition 、その場所にを設定します。
    • このreturnステートメントは 、RestaurantListコンポーネントと Map コンポーネントをラップする<div>要素を返します。 RestaurantList コンポーネントは restaurantList という名前の prop として配列を渡し listonClickHandler_ 関数はという名前の prop として渡さ onClickHandlerれます。 Map コンポーネントは apikeyuserPosition、、およびrestaurantPositionの変数をプロパティとして渡します。
  6. ファイルを保存します。

結果: ブラウザウィンドウに RestaurantList コンポーネントが表示されます。 このコンポーネント内では、次 RestaurantEntry の図に示すように、各レストランが個別のコンポーネントとして表示されます。 RestaurantList 、 RestaurantEntry 、および Map の各コンポーネントがブラウザウィンドウに表示されます

REACT コンポーネント間の対話性を導入します

インタラクティブ性を高めるため Map に、ユーザーの位置を表すマーカー、レストランの位置を表すマーカー、およびそれらの間で計算された最速ルートを表示するようにコンポーネントを設定できます。 この設定は、ユーザーが RestaurantEntry コンポーネントをクリックするとトリガされます。

  1. Map.jsMap の例に示すように、ファイルの関数で props オブジェクトを更新し、ユーザーおよびレストランの位置を抽出します。

     const Map = (props) => {
       const mapRef = useRef(null);
       const map = useRef(null);
       const platform = useRef(null);
       const { apikey, userPosition, restaurantPosition } = props;
    
  2. useEffect の例に示すように、フックの dependencies 配列にユーザーとレストランの場所を追加します。

     import { useEffect } from 'react';
    
     const Map = ( props ) => {
     useEffect(() => {
         // Hook definition...
       }, 
      // Dependencies array 
      [apiKey, userPosition, restaurantPosition]);
     };
    
  3. 次の例に示すように、現在のマップの中心を現在のユーザーの位置と同じ値に変更します。

     const newMap = new H.Map(
         mapRef.current,
         rasterTileLayer, {
             pixelRatio: window.devicePixelRatio,
             center: userPosition,
             zoom: 14,
         },
     );
    
  4. マーカーアイコンのスタイルを設定する関数を定義します。

     function getMarkerIcon(color) {
         const svgCircle = `<svg width="20" height="20" version="1.1" xmlns="http://www.w3.org/2000/svg">
                     <g id="marker">
                     <circle cx="10" cy="10" r="7" fill="${color}" stroke="${color}" stroke-width="4" />
                     </g></svg>`;
         return new H.map.Icon(svgCircle, {
             anchor: {
                 x: 10,
                 y: 10
             }
         });
     }
    
  5. HERE Routing API V8 を使用して、ユーザーとレストラン間の最速ルートを計算します。

     function calculateRoute(platform, map, start, destination) {
         function routeResponseHandler(response) {
             const sections = response.routes[0].sections;
             const lineStrings = [];
             sections.forEach((section) => {
                 // convert Flexible Polyline encoded string to geometry
                 lineStrings.push(H.geo.LineString.fromFlexiblePolyline(section.polyline));
             });
             const multiLineString = new H.geo.MultiLineString(lineStrings);
             const bounds = multiLineString.getBoundingBox();
    
             // Create the polyline for the route
             const routePolyline = new H.map.Polyline(multiLineString, {
                 style: {
                     lineWidth: 5
                 }
             });
    
             // Remove all the previous map objects, if any
             map.removeObjects(map.getObjects());
             // Add the polyline to the map
             map.addObject(routePolyline);
             map.addObjects([
                 // Add a marker for the user
                 new H.map.Marker(start, {
                     icon: getMarkerIcon('red')
                 }),
                 // Add a marker for the selected restaurant
                 new H.map.Marker(destination, {
                     icon: getMarkerIcon('green')
                 })
             ]);
         }
    
         // Get an instance of the H.service.RoutingService8 service
         const router = platform.getRoutingService(null, 8);
    
         // Define the routing service parameters
         const routingParams = {
             'origin': `${start.lat},${start.lng}`,
             'destination': `${destination.lat},${destination.lng}`,
             'transportMode': 'car',
             'return': 'polyline'
         };
         // Call the routing service with the defined parameters
         router.calculateRoute(routingParams, routeResponseHandler, console.error);
     }
    

    このコードは、ルート計算プロセスを設定し、応答を処理して、計算されたルート、ユーザーマーカー、および宛先マーカーをマップに表示します。 詳細については、以下を参照してください。

  6. Map コンポーネントのuseEffectフックにコードを追加して 、restaurantPosition正しいかどうかを確認します。

     if (restaurantPosition) {
         calculateRoute(platform.current, map.current, userPosition, restaurantPosition);
     }
    

    restaurantPosition が定義されている場合、コードはユーザーの位置からレストランの位置までのルートを計算して地図に表示します。

  7. ファイルを保存します。

結果: 次の例に示すように、ユーザーの場所と選択したレストランの間の最速ルートを計算できるようになりました。 React コンポーネントとの HERE Maps API の統合

チュートリアルの手順に従うことで、 Maps API for JavaScript を反応機能コンポーネントと統合して、位置情報ベースの機能をアプリケーションに組み込み、ユーザーの操作を処理する方法を学習しました。

任意 : アプリケーションのスタイルを設定します

スタイリングの改善により、コンポーネントの魅力を高め、視覚的にユーザーにアピールすることで、アプリケーションをさらに改善できます。

たとえば、 CSS を使用すると App 、コンポーネント内の個 RestaurantEntry 々のコンポーネントの配置を調整してコンポーネントの視覚的な外観を改善できます。また、丸みのある境界線を使用して、マウスオーバー状態に基づいてボタンの色のバリエーションを追加し、各エントリの追加データを表示できます。 コンポーネントの上部にバナーを配置 RestaurantList するなどの操作を行います。

次の図は、 このチュートリアルで作成した RestaurantListコンポーネントおよびRestaurantEntryコンポーネントに適用されているサンプルのスタイルを示しています。 スタイリングされた構成要素を使用してアプリケーションに反応

詳細 については、 Cascading Style Sheets (CSS) のドキュメントを参照してください。

次のステップ

その他の使用例の詳細について は、『 Maps API for JavaScript Guide 』を参照してください。

」に一致する結果は 件です

    」に一致する結果はありません