プレイス検索要素と Maps JavaScript API を使用して場所を検索する

目標

Place Search Element を Google マップに統合して、ユーザーが周辺検索やテキスト検索で場所を見つけられるようにし、スポットを探索する機能を強化する方法について説明します。Place Details Compact 要素を使用して、アプリに表示される場所に関する詳細情報を提供します。

プレイス検索要素とは

Place Search 要素は、Maps JavaScript API の Places UI キットの一部です。これは、アプリケーション内のリスト形式で場所検索の結果を直接レンダリングする HTML 要素です。この要素により、Nearby Search または Text Search で見つかった場所を表示するプロセスが簡素化され、場所の検索でシームレスなユーザー エクスペリエンスが実現します。ユーザーがリストから場所を選択すると、多くの場合、情報ウィンドウと Place Details 要素を使用して、その場所の詳細を地図上に表示できます。

場所の見つけやすさを可視化する

次の画像は、Place Search Element の動作例を示しています。左側には、レストランの一覧が表示されます(Place Search Element)。レストランを選択すると、地図上の情報ウィンドウにその詳細が表示され、地図はその場所を中心に表示されます。

画像

プレイス ディスカバリのユースケース

プレイス検索要素を統合すると、さまざまな業界のさまざまなアプリケーションを強化できます。

  • 旅行と観光: 特定の地域の観光スポット、ホテル、特定の種類の料理を観光客が検索できるようにします。
  • 不動産: 購入や賃貸を検討しているユーザーが、近くの学校、スーパーマーケット、公共交通機関を見つけられるようにします。
  • 物流とサービス: ドライバーが EV 充電スタンド、ガソリン スタンド、特定のサービス センターを見つけるのを支援します。

ソリューションのワークフロー: Place Discovery の実装

このセクションでは、地図上の場所を検出するための Place Search Element を統合する手順について説明します。これには、Places UI Kit を操作するためのコード スニペットも含まれます。このガイドでは、地図の初期化と、Nearby Search と Text Search の両方の機能の実装について説明します。最後に、Place Details 要素を使用して、地図上のピンをクリックしたときに特定の場所の詳細を表示します。

前提条件

次のドキュメントをよく読むことをおすすめします。

  • Place Search 要素 - Nearby Search または Text Search を使用して場所を公開するために使用されます
  • Place Details 要素 - 個々の場所の詳細を表示するために使用されます
  • Maps JavaScript API - ページに地図を表示し、Places UI Kit をインポートするために使用されます。

プロジェクトで Maps JavaScript APIPlaces UI Kit を有効にします。

開始する前に、Maps JavaScript API を読み込み、必要なライブラリをインポートしていることを確認してください。また、このドキュメントは、HTML、CSS、JavaScript などのウェブ開発に関する実践的な知識があることを前提としています。

ページに地図を追加する

まず、ページに地図を追加します。この地図は、場所検索要素の結果を選択可能なピンとして表示するために使用されます。

ページに地図を追加する方法は 2 つあります。

  1. gmp-map HTML ウェブ コンポーネントを使用する。
  2. JavaScript を使用します。

このページのコード スニペットは、JavaScript マップを使用して生成されました。

地図は、ユーザーに検索してほしい場所(ホテルなど)を中心に表示することも、ユーザーの現在地を尋ねて地図の中心に表示するように初期化することもできます。このドキュメントでは、検索の基準となる固定位置を使用します。

ホテルなどの固定された場所の近くにある場所を可視化する場合は、地図上にマーカーを配置して、その場所を表します。次に例を示します。

画像

地図の中心はサンフランシスコで、青いピンは近くで検索している場所を表しています。ピンの色は PinElement を使用してカスタマイズされています。地図タイプ コントロールが UI から非表示になりました。

Place Search 要素を設定する

これで、HTML と CSS を設定して Place Search Element を表示できるようになりました。この例では、要素を地図の左側にフロートしますが、アプリケーションに合わせてさまざまなレイアウトを試すことをおすすめします。

Place Search Element は宣言型アプローチを使用します。JavaScript で完全に構成する代わりに、<gmp-place-nearby-search-request> などのリクエスト要素をメインの <gmp-place-search> コンポーネント内にネストすることで、HTML で検索タイプを直接定義します。

HTML コード内で、<gmp-place-search> 要素を初期化します。selectable 属性を使用して、結果のクリック イベントを有効にします。その中に <gmp-place-nearby-search-request> を追加して、この要素が近隣検索に使用されることを指定します。

<gmp-place-search selectable>
  <gmp-place-nearby-search-request>
  </gmp-place-nearby-search-request>
</gmp-place-search>

最初の検索を実行して結果を表示するには、JavaScript を使用してネストされたリクエスト要素への参照を取得し、そのプロパティを設定します。前のステップのマーカーの位置を中心点として使用し、locationRestriction として使用する Circle を初期化します。次に、リクエスト要素の locationRestriction プロパティと includedPrimaryTypes プロパティを設定して、検索をトリガーします。

このコード スニペットは次のとおりです。

// Get references to the Place Search and its nested request element
const placeSearchElement = document.querySelector("gmp-place-search");
const placeSearchRequestElement = document.querySelector("gmp-place-nearby-search-request");

// Define the location restriction for the search
const circleRestriction = new Circle({
    center: marker.position,
    radius: 500
});

// Set the properties on the request element to perform an initial search for restaurants.
placeSearchRequestElement.locationRestriction = circleRestriction;
placeSearchRequestElement.includedPrimaryTypes = ['restaurant'];

この段階でのアプリケーションの例を次に示します。

画像

Place Search Element では、次の 2 つの検索オプションを使用できます。

  • <gmp-place-nearby-search-request> - 場所タイプを使用して、Places Nearby Search の検索結果をレンダリングします。
  • <gmp-place-text-search-request> - 「サンフランシスコの寿司」などのフリーテキスト入力を使用して、プレイス テキスト検索の検索結果をレンダリングします。

これらは <gmp-place-search> 内のネストされた要素です。次に、JavaScript を使用して、そのネストされたリクエスト要素のプロパティを設定して検索をトリガーします。

このセクションでは、両方のメソッドの実装について説明します。

画像

ユーザーが付近の検索を実行できるようにするには、まず 場所のタイプを選択するための UI 要素が必要です。アプリケーションに最適な選択方法を選択します(場所の種類の選択肢が入力されたプルダウン リストなど)。

ユースケースに関連するタイプのサブセットを選択することをおすすめします。たとえば、ホテル周辺の観光スポットを観光客に表示するアプリを開発している場合は、bakerycoffee_shopmuseumrestauranttourist_attraction を選択できます。

HTML には、<gmp-place-nearby-search-request> がネストされた <gmp-place-search> 要素を含める必要があります。

<gmp-place-search selectable>
  <gmp-place-nearby-search-request>
  </gmp-place-nearby-search-request>
</gmp-place-search>

次に、場所タイプのセレクタで change イベントの JavaScript リスナーを作成します。このリスナーは、<gmp-place-nearby-search-request> 要素のプロパティを更新する関数を呼び出します。これにより、新しい検索が自動的にトリガーされ、リストが更新されます。

// Get a reference to the nested request element
const placeSearchRequestElement = document.querySelector('gmp-place-nearby-search-request');

// Function to update the place search based on the selected type
function updatePlaceList() {
    const selectedType = placeTypeSelect.value;
    if (!selectedType) {
        // If no type is selected, don't perform a search.
        // You could optionally hide the list or clear previous results here.
        placeSearchElement.style.display = 'none';
        return;
    }
    placeSearchElement.style.display = 'block';

    // Set properties on the request element to trigger a new search
    placeSearchRequestElement.locationRestriction = searchCircle;
    placeSearchRequestElement.maxResultCount = 8;
    placeSearchRequestElement.includedPrimaryTypes = [selectedType];
}

設定ステップと同じ searchCirclelocationRestriction に使用されます。includedPrimaryTypes プロパティは、ユーザーの選択から取得した値に設定されます。オプションの maxResultCount も設定して、結果の数を制限します。

画像

テキスト検索を有効にするには、HTML 構成を変更する必要があります。近隣検索リクエストの代わりに、<gmp-place-text-search-request> 要素をネストします。

<gmp-place-search selectable>
  <gmp-place-text-search-request>
  </gmp-place-text-search-request>
</gmp-place-search>

UI にテキスト入力と検索ボタンを追加します。ボタンの click イベントの JavaScript リスナーを作成します。イベント ハンドラはユーザーの入力を受け取り、<gmp-place-text-search-request> 要素のプロパティを更新して検索を実行します。

// Get a reference to the text search request element
const placeTextSearchRequestElement = document.querySelector('gmp-place-text-search-request');
const textSearchInput = document.getElementById('textSearchInput');
const textSearchButton = document.getElementById('textSearchButton');

textSearchButton.addEventListener('click', performTextSearch);

function performTextSearch() {
    const query = textSearchInput.value.trim();
    if (!query) {
        console.log("Search query is empty.");
        return;
    }
    // Set properties on the request element to trigger a new search
    placeTextSearchRequestElement.textQuery = query;
    placeTextSearchRequestElement.locationBias = map.getBounds();
    placeTextSearchRequestElement.maxResultCount = 8;
}

ここでは、ユーザーの入力で textQuery プロパティを設定しています。また、現在の地図の境界線を使用する locationBias も提供しています。これにより、API はそのエリア内の結果を優先しますが、厳密に制限はしません。オプションの maxResultCount は、返される結果の数を制限します。

場所のピンと詳細を表示する

これで、アプリは場所の検索を実行して要素を入力できます。次のステップでは、次の方法で機能を強化します。

  • 場所検索要素に入力された各場所のピンを地図上に表示します。
  • ユーザーがピンまたは Place Search Element 内の場所をクリックして、その特定の場所に関する詳細を表示できるようにします。

この手順の原則は、アプリが周辺検索を使用しているかテキスト検索を使用しているかに関係なく同じです。

まず、JavaScript コードにグローバル変数(プレイスマーカーを格納する変数)を追加します。これにより、検索が変更されたときに削除し、クリック イベントを処理できます。

let markers = {};

地図にマーカーを追加する関数を作成します。この関数は、新しい検索結果が読み込まれるたびに呼び出されます。次のようになります。

  • 地図から既存の場所マーカーを削除します。
  • プレイス検索要素の結果をループ処理し、それぞれにマーカーを追加します。
  • 新しいマーカーがすべて表示されるように地図の境界を調整します。

検索結果が利用可能になったときにリッスンするには、<gmp-place-search> 要素に gmp-load イベント リスナーを追加します。このイベントは、検索が完了して結果がレンダリングされた後に発生します。

リスナーは検索関数内に追加します(例: updatePlaceList)を渡します。また、{ once: true } オプションを使用して、現在の検索結果に対してのみ発火するようにします。

// In your search function, after setting the request properties:
placeSearchElement.addEventListener('gmp-load', addMarkers, { once: true });

addMarkers 関数は次のようになります。

async function addMarkers() {
    const { LatLngBounds } = await google.maps.importLibrary("core");
    const bounds = new LatLngBounds();

    if (placeSearchElement.places.length > 0) {
        // Remove existing markers
        for (const m in markers) {
            markers[m].map = null;
        }
        markers = {};

        // Loop through each place from the search results
        // and add a marker for each one.
        for (const place of placeSearchElement.places) {
            const marker = new google.maps.marker.AdvancedMarkerElement({
                map: map,
                position: place.location,
            });

            markers[place.id] = marker;
            bounds.extend(place.location);
            marker.collisionBehavior = google.maps.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL;

            // Add a click listener for each marker.
            marker.addListener('gmp-click', (event) => {
                // The main logic for showing details will go here.
            });
        }
        // Position the map to display all markers.
        map.setCenter(bounds.getCenter());
        map.fitBounds(bounds);
    }
}

この手順が完了すると、アプリケーションは次のようになり、Place Search Element から返された各場所のマーカーを表示できるようになります。

画像

マップにマーカーが表示されたので、最後のステップとして、マーカーと要素のクリック イベントを処理して、Place Details Element によって提供される場所の詳細を含む情報ウィンドウを表示します。この例では、Place Details Compact Element を使用します。

コードに Place Details Compact Element の HTML を追加します。例:

<gmp-place-details-compact orientation="vertical" style="display: none;">
    <gmp-place-all-content></gmp-place-all-content>
    <gmp-place-attribution light-scheme-color="gray" dark-scheme-color="white"></gmp-place-attribution>
</gmp-place-details-compact>

styledisplay: none に設定されています。必要になるまで表示されません。gmp-place-all-content は、すべての要素コンテンツをレンダリングするために渡されます。レンダリングするコンテンツを選択するには、Place Details Compact 要素のドキュメントをご覧ください。

JavaScript で、Place Details Compact Element への参照を保持するグローバル変数を作成し、初期化コードでこの変数を設定します。例:

let placeDetailsElement;
...
placeDetailsElement = document.querySelector('gmp-place-details-compact');

addMarkers 関数内で、各マーカーに gmp-click イベント リスナーを追加し、現在のマーカーのプレイス ID を渡して、プレイスの詳細を表示するようにプレイスの詳細コンパクト要素を構成します。

完了すると、マーカーにアンカー設定された場所の詳細コンパクト要素を表示する情報ウィンドウが開きます。

最後に、地図が選択した場所のビューポートに配置され、表示されます。

async function addMarkers() {
          ...
            marker.addListener('gmp-click', (event) => {
                //Set up Place Details Compact Widget
                placeDetailsElement.style.display = "block";
                // Remove any existing place request element
                const existingPlaceRequest = placeDetailsElement.querySelector('gmp-place-details-place-request');
                if (existingPlaceRequest) {
                    existingPlaceRequest.remove();
                }
                // Create and configure the new place request element
                const placeRequestElement = new google.maps.places.PlaceDetailsPlaceRequestElement({ place: place.id });
                // Prepend the new place request element to the main widget
                placeDetailsElement.prepend(placeRequestElement);
                if (infoWindow.isOpen) {
                    infoWindow.close();
                }
                infoWindow.setOptions({
                    content: placeDetailsElement
                });
                infoWindow.open({
                    anchor: marker,
                    map: map
                });
                // Position the map to show the selected place
                placeDetailsElement.addEventListener('gmp-load', () => {
                    map.fitBounds(place.viewport, { top: 500, left: 400 });
                });
            });
          ...
        });
    }
}

ユーザーが Place List Element の場所をクリックして Place Details Compact Element を表示できるようにするには、configureFromSearchNearbyRequest の呼び出し後に次のコードを JavaScript コードに追加します。

placeSearchElement.addEventListener("gmp-select", ({ place }) => {
    if (markers[place.id]) {
        markers[place.id].click();
    }
});

この手順を完了すると、アプリケーションは Nearby Search または Text Search を使用して Place List Element を入力できるようになります。この結果、地図上にピンが表示されます。ピンまたは Place List Element の場所をクリックすると、Place Details Compact Element によって提供される場所の詳細を含む情報ウィンドウが表示されます。

アプリケーションは次のようになります。

画像

まとめ

プレイス検索要素とプレイス詳細コンパクト要素を組み合わせることで、Google Maps Platform アプリケーションに豊富なプレイス検索機能を効率的に追加できます。

Places UI キットを今すぐお試しください。ユーザーは、近隣検索とテキスト検索の両方を使用して場所を検索、探索し、豊富な場所の詳細情報を表示して、場所の発見に関するユースケースでの操作性を高めることができます。

寄稿者

DevX エンジニア | Henrik Valve