Membuat pencari toko sederhana dengan Google Maps Platform (JavaScript)

1. Sebelum memulai

Salah satu fitur paling umum pada situs adalah menampilkan peta Google yang menandai satu atau beberapa lokasi untuk bisnis, tempat usaha, atau sejumlah entitas lainnya dengan kehadiran fisik. Cara penerapan peta ini dapat sangat bervariasi bergantung pada persyaratan, seperti jumlah lokasi dan frekuensi perubahannya.

Di codelab ini, Anda melihat kasus penggunaan yang paling sederhana—sejumlah kecil lokasi yang jarang berubah, seperti pencari toko untuk bisnis dengan jaringan toko. Dalam hal ini, Anda dapat menggunakan pendekatan teknologi yang relatif rendah tanpa pemrograman sisi server. Namun, ini bukan berarti Anda tidak bisa berkreasi, Anda dapat melakukannya dengan memanfaatkan format data GeoJSON untuk menyimpan dan merender informasi arbitrer tentang setiap toko di peta Anda, serta menyesuaikan penanda dan keseluruhan gaya peta itu sendiri.

Terakhir, sebagai bonus tambahan, Anda menggunakan Cloud Shell untuk mengembangkan dan menghosting pencari toko. Meskipun penggunaan alat ini tidak wajib, tindakan ini memungkinkan Anda mengembangkan pencari toko dari semua perangkat yang menjalankan browser web dan membuatnya tersedia secara online untuk publik.

489628918395c3d0.png

Prasyarat

  • Pengetahuan dasar tentang HTML dan JavaScript

Yang akan Anda lakukan

  • Menampilkan peta dengan sekumpulan lokasi toko dan informasi yang disimpan dalam format GeoJSON.
  • Menyesuaikan penanda dan peta itu sendiri.
  • Menampilkan informasi tambahan tentang toko saat penandanya diklik.
  • Menambahkan kotak penelusuran Place Autocomplete ke halaman web.
  • Mengidentifikasi lokasi toko yang paling dekat dengan titik awal yang diberikan pengguna.

2. Memulai persiapan

Pada Langkah 3 di bagian berikut, aktifkan tiga API berikut untuk codelab ini:

  • Maps JavaScript API
  • Places API
  • Distance Matrix API

Memulai Google Maps Platform

Jika Anda belum pernah menggunakan Google Maps Platform, ikuti panduan Memulai Google Maps Platform atau tonton playlist Memulai Google Maps Platform untuk menyelesaikan langkah-langkah berikut:

  1. Membuat akun penagihan.
  2. Membuat project.
  3. Mengaktifkan API dan SDK Google Maps Platform (tercantum di bagian sebelumnya).
  4. Membuat kunci API.

Mengaktifkan Cloud Shell

Di codelab ini, Anda menggunakan Cloud Shell, lingkungan command line yang berjalan di Google Cloud yang menyediakan akses ke produk dan resource yang berjalan di Google Cloud, sehingga Anda dapat menghosting dan menjalankan project sepenuhnya dari browser web.

Untuk mengaktifkan Cloud Shell dari Cloud Console, klik Aktifkan Cloud Shell 89665d8d348105cd.png (hanya perlu waktu beberapa saat untuk penyediaan dan koneksi ke lingkungan).

5f504766b9b3be17.png

Tindakan ini akan membuka shell baru di bagian bawah browser setelah kemungkinan menampilkan interstisial pengantar.

d3bb67d514893d1f.png

Setelah terhubung ke Cloud Shell, Anda akan melihat bahwa Anda telah diautentikasi dan project tersebut telah ditetapkan ke project ID yang Anda pilih selama penyiapan.

$ gcloud auth list
Credentialed Accounts:
ACTIVE  ACCOUNT
  *     <myaccount>@<mydomain>.com
$ gcloud config list project
[core]
project = <YOUR_PROJECT_ID>

Jika project belum ditetapkan karena beberapa alasan, jalankan perintah berikut:

$ gcloud config set project <YOUR_PROJECT_ID>

3. "Halo Dunia!" dengan peta

Mulai mengembangkan dengan peta

Di Cloud Shell, Anda mulai dengan membuat halaman HTML yang akan berfungsi sebagai dasar untuk codelab lainnya.

  1. Di toolbar Cloud Shell, klik Luncurkan Editor 996514928389de40.png untuk membuka editor kode di tab baru.

Editor kode berbasis web ini memungkinkan Anda mengedit file di Cloud Shell dengan mudah.

Screen Shot 2017-04-19 at 10.22.48 AM.png

  1. Buat direktori store-locator baru untuk aplikasi Anda di editor kode dengan mengklik File > Folder Baru.

NewFolder.png

  1. Beri nama folder baru store-locator.

Selanjutnya, Anda membuat halaman web dengan peta.

  1. Buat file di direktori store-locator bernama index.html.

3c257603da5ab524.png

  1. Masukkan konten berikut dalam file index.html:

index.html

<html>

<head>
    <title>Store Locator</title>
    <style>
        #map {
            height: 100%;
        }

        html,
        body {
            height: 100%;
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>
    <!-- The div to hold the map -->
    <div id="map"></div>

    <script src="app.js"></script>
    <script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap&solution_channel=GMP_codelabs_simplestorelocator_v1_a">
    </script>
</body>

</html>

Ini adalah halaman HTML yang menampilkan peta. File ini berisi beberapa CSS untuk memastikan peta mengisi seluruh halaman secara visual, tag <div> untuk menyimpan peta, dan sepasang tag <script>. Tag skrip pertama memuat file JavaScript yang disebut app.js, yang berisi semua kode JavaScript. Tag skrip kedua memuat kunci API, termasuk penggunaan Places Library untuk fungsi pelengkapan otomatis yang akan Anda tambahkan nanti, dan menentukan nama fungsi JavaScript yang dijalankan setelah Maps JavaScript API dimuat, yaitu initMap.

  1. Ganti teks YOUR_API_KEY di cuplikan kode dengan kunci API yang Anda buat sebelumnya di codelab ini.
  2. Terakhir, buat file lain bernama app.js dengan kode berikut:

app.js

function initMap() {
   // Create the map.
    const map = new google.maps.Map(document.getElementById('map'), {
        zoom: 7,
        center: { lat: 52.632469, lng: -1.689423 },
    });

}

Itu adalah kode minimum yang diperlukan untuk membuat peta. Anda meneruskan referensi ke tag <div> untuk menyimpan peta, dan menentukan pusat dan tingkat zoom.

Untuk menguji aplikasi ini, Anda dapat menjalankan server HTTP Python yang sederhana di Cloud Shell.

  1. Buka Cloud Shell dan ketik hal berikut:
$ cd store-locator
$ python -m SimpleHTTPServer 8080

Anda melihat beberapa baris output log yang menunjukkan bahwa Anda memang menjalankan server HTTP sederhana di Cloud Shell dengan aplikasi web yang diproses di port localhost 8080.

  1. Buka tab browser web di aplikasi ini dengan mengklik Pratinjau Web 95e419ae763a1d48.png di toolbar Cloud Console dan memilih Pratinjau di port 8080.

47b06e5169eb5add.png

bdab1f021a3b91d5.png

Mengklik item menu ini akan membuka tab baru di browser web Anda dengan konten HTML yang ditayangkan dari server HTTP Python sederhana. Jika semuanya berjalan lancar, Anda akan melihat peta yang berpusat di London, Inggris.

Untuk menghentikan server HTTP sederhana, tekan Control+C di Cloud Shell.

4. Mengisi peta dengan GeoJSON

Sekarang, lihat data untuk toko. GeoJSON adalah format data yang mewakili fitur geografis sederhana, seperti titik, garis, atau poligon di peta. Fitur tersebut juga dapat berisi data arbitrer. Hal ini menjadikan GeoJSON kandidat yang sangat tepat untuk mewakili toko, yang pada dasarnya adalah titik di peta dengan sedikit data tambahan, seperti nama toko, jam buka, dan nomor telepon. Yang terpenting, GeoJSON memiliki dukungan kelas satu di Google Maps, yang berarti Anda dapat mengirim dokumen GeoJSON ke peta Google yang akan merendernya di peta dengan tepat.

  1. Buat file baru bernama stores.json lalu tempelkan kode berikut:

stores.json

{
    "type": "FeatureCollection",
    "features": [{
            "geometry": {
                "type": "Point",
                "coordinates": [-0.1428115,
                    51.5125168
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Modern twists on classic pastries. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Patisserie Mayfair",
                "phone": "+44 20 1234 5678",
                "storeid": "01"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-2.579623,
                    51.452251
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Come and try our award-winning cakes and pastries. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Patisserie Bristol",
                "phone": "+44 117 121 2121",
                "storeid": "02"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    1.273459,
                    52.638072
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Whatever the occasion, whether it's a birthday or a wedding, Josie's Patisserie has the perfect treat for you. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Patisserie Norwich",
                "phone": "+44 1603 123456",
                "storeid": "03"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-1.9912838,
                    50.8000418
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "A gourmet patisserie that will delight your senses. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Patisserie Wimborne",
                "phone": "+44 1202 343434",
                "storeid": "04"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-2.985933,
                    53.408899
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Spoil yourself or someone special with our classic pastries. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Patisserie Liverpool",
                "phone": "+44 151 444 4444",
                "storeid": "05"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-1.689423,
                    52.632469
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Come and feast your eyes and tastebuds on our delicious pastries and cakes. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Patisserie Tamworth",
                "phone": "+44 5555 55555",
                "storeid": "06"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-3.155305,
                    51.479756
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "patisserie",
                "hours": "10am - 6pm",
                "description": "Josie's Patisserie is family-owned, and our delectable pastries, cakes, and great coffee are renowed. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Patisserie Cardiff",
                "phone": "+44 29 6666 6666",
                "storeid": "07"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-0.725019,
                    52.668891
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "Oakham's favorite spot for fresh coffee and delicious cakes. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Cafe Oakham",
                "phone": "+44 7777 777777",
                "storeid": "08"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-2.477653,
                    53.735405
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "Enjoy freshly brewed coffe, and home baked cakes in our homely cafe. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Cafe Blackburn",
                "phone": "+44 8888 88888",
                "storeid": "09"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-0.211363,
                    51.108966
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "A delicious array of pastries with many flavours, and fresh coffee in an snug cafe. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Cafe Crawley",
                "phone": "+44 1010 101010",
                "storeid": "10"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-0.123559,
                    50.832679
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "Grab a freshly brewed coffee, a decadent cake and relax in our idyllic cafe. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Cafe Brighton",
                "phone": "+44 1313 131313",
                "storeid": "11"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-3.319575,
                    52.517827
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "Come in and unwind at this idyllic cafe with fresh coffee and home made cakes. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Cafe Newtown",
                "phone": "+44 1414 141414",
                "storeid": "12"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    1.158167,
                    52.071634
                ]
            },
            "type": "Feature",
            "properties": {
                "category": "cafe",
                "hours": "8am - 9:30pm",
                "description": "Fresh coffee and delicious cakes in an snug cafe. We're part of a larger chain of patisseries and cafes.",
                "name": "Josie's Cafe Ipswich",
                "phone": "+44 1717 17171",
                "storeid": "13"
            }
        }
    ]
}

Datanya banyak sekali. Namun, jika Anda amati, data tersebut memiliki struktur yang sama dan diulang untuk setiap toko. Setiap toko ditampilkan sebagai Point GeoJSON beserta koordinatnya dan data tambahan yang terdapat di bagian kunci properties. Menariknya, GeoJSON mengizinkan penyertaan kunci yang diberi nama secara arbitrer di bagian kunci properties. Di codelab ini, kunci tersebut adalah category, hours, description, name, dan phone.

  1. Sekarang edit app.js agar GeoJSON dimuat di stores.js ke peta Anda.

app.js

function initMap() {
  // Create the map.
  const map = new google.maps.Map(document.getElementById('map'), {
    zoom: 7,
    center: {lat: 52.632469, lng: -1.689423},
  });

  // Load the stores GeoJSON onto the map.
  map.data.loadGeoJson('stores.json', {idPropertyName: 'storeid'});

  const apiKey = 'YOUR_API_KEY';
  const infoWindow = new google.maps.InfoWindow();

  // Show the information for a store when its marker is clicked.
  map.data.addListener('click', (event) => {
    const category = event.feature.getProperty('category');
    const name = event.feature.getProperty('name');
    const description = event.feature.getProperty('description');
    const hours = event.feature.getProperty('hours');
    const phone = event.feature.getProperty('phone');
    const position = event.feature.getGeometry().get();
    const content = `
      <h2>${name}</h2><p>${description}</p>
      <p><b>Open:</b> ${hours}<br/><b>Phone:</b> ${phone}</p>
    `;

    infoWindow.setContent(content);
    infoWindow.setPosition(position);
    infoWindow.setOptions({pixelOffset: new google.maps.Size(0, -30)});
    infoWindow.open(map);
  });
}

Dalam contoh kode, Anda telah memuat GeoJSON ke peta dengan memanggil loadGeoJson dan meneruskan nama file JSON. Anda juga telah menentukan fungsi untuk dijalankan setiap kali penanda diklik. Fungsi tersebut kemudian dapat mengakses data tambahan untuk toko yang penandanya diklik dan menggunakan informasi di jendela info yang ditampilkan. Untuk menguji aplikasi ini, Anda dapat menjalankan server HTTP Python sederhana menggunakan perintah yang sama seperti sebelumnya.

  1. Kembali ke Cloud Shell dan ketik hal berikut:
$ python -m SimpleHTTPServer 8080
  1. Klik lagi Pratinjau Web 95e419ae763a1d48.png > Pratinjau di port 8080 dan Anda akan melihat peta penuh penanda yang dapat diklik untuk melihat detail tentang setiap toko, seperti contoh berikut. Progres!

c4507f7d3ea18439.png

5. Menyesuaikan peta

Anda hampir selesai. Anda memiliki peta dengan semua penanda toko dan informasi tambahan yang ditampilkan saat diklik. Namun, tampilannya mirip seperti semua peta Google lainnya di luar sana. Sungguh membosankan! Kreasikan agar terlihat menarik dengan gaya peta kustom, penanda, logo, dan gambar Street View.

Berikut adalah app.js versi baru dengan penambahan gaya visual kustom:

app.js

const mapStyle = [{
  'featureType': 'administrative',
  'elementType': 'all',
  'stylers': [{
    'visibility': 'on',
  },
  {
    'lightness': 33,
  },
  ],
},
{
  'featureType': 'landscape',
  'elementType': 'all',
  'stylers': [{
    'color': '#f2e5d4',
  }],
},
{
  'featureType': 'poi.park',
  'elementType': 'geometry',
  'stylers': [{
    'color': '#c5dac6',
  }],
},
{
  'featureType': 'poi.park',
  'elementType': 'labels',
  'stylers': [{
    'visibility': 'on',
  },
  {
    'lightness': 20,
  },
  ],
},
{
  'featureType': 'road',
  'elementType': 'all',
  'stylers': [{
    'lightness': 20,
  }],
},
{
  'featureType': 'road.highway',
  'elementType': 'geometry',
  'stylers': [{
    'color': '#c5c6c6',
  }],
},
{
  'featureType': 'road.arterial',
  'elementType': 'geometry',
  'stylers': [{
    'color': '#e4d7c6',
  }],
},
{
  'featureType': 'road.local',
  'elementType': 'geometry',
  'stylers': [{
    'color': '#fbfaf7',
  }],
},
{
  'featureType': 'water',
  'elementType': 'all',
  'stylers': [{
    'visibility': 'on',
  },
  {
    'color': '#acbcc9',
  },
  ],
},
];

function initMap() {
  // Create the map.
  const map = new google.maps.Map(document.getElementById('map'), {
    zoom: 7,
    center: {lat: 52.632469, lng: -1.689423},
    styles: mapStyle,
  });

  // Load the stores GeoJSON onto the map.
  map.data.loadGeoJson('stores.json', {idPropertyName: 'storeid'});

  // Define the custom marker icons, using the store's "category".
  map.data.setStyle((feature) => {
    return {
      icon: {
        url: `img/icon_${feature.getProperty('category')}.png`,
        scaledSize: new google.maps.Size(64, 64),
      },
    };
  });

  const apiKey = 'YOUR_API_KEY';
  const infoWindow = new google.maps.InfoWindow();

  // Show the information for a store when its marker is clicked.
  map.data.addListener('click', (event) => {
    const category = event.feature.getProperty('category');
    const name = event.feature.getProperty('name');
    const description = event.feature.getProperty('description');
    const hours = event.feature.getProperty('hours');
    const phone = event.feature.getProperty('phone');
    const position = event.feature.getGeometry().get();
    const content = `
      <img style="float:left; width:200px; margin-top:30px" src="img/logo_${category}.png">
      <div style="margin-left:220px; margin-bottom:20px;">
        <h2>${name}</h2><p>${description}</p>
        <p><b>Open:</b> ${hours}<br/><b>Phone:</b> ${phone}</p>
        <p><img src="https://maps.googleapis.com/maps/api/streetview?size=350x120&location=${position.lat()},${position.lng()}&key=${apiKey}&solution_channel=GMP_codelabs_simplestorelocator_v1_a"></p>
      </div>
      `;

    infoWindow.setContent(content);
    infoWindow.setPosition(position);
    infoWindow.setOptions({pixelOffset: new google.maps.Size(0, -30)});
    infoWindow.open(map);
  });

}

Berikut hal-hal yang Anda tambahkan:

  • Variabel mapStyle berisi semua informasi untuk menata gaya peta. (Sebagai bonus tambahan, Anda bahkan dapat membuat gaya Anda sendiri jika menginginkannya.)
  • Dengan menggunakan metode map.data.setStyle, Anda menerapkan penanda khusus—penanda yang berbeda untuk setiap category dari GeoJSON.
  • Anda mengubah variabel content untuk menyertakan logo (sekali lagi menggunakan category dari GeoJSON) dan gambar Street View untuk lokasi toko.

Sebelum men-deploy ini, Anda harus menyelesaikan beberapa langkah:

  1. Tetapkan nilai yang benar untuk variabel apiKey dengan mengganti string 'YOUR_API_KEY' di app.js dengan kunci API Anda sendiri dari tahap sebelumnya (kunci yang sama yang Anda tempelkan di index.html, sehingga tanda kutip tidak berubah).
  2. Jalankan perintah berikut di Cloud Shell untuk mendownload gambar logo dan penanda. Pastikan Anda berada di direktori store-locator. Gunakan Control+C untuk menghentikan server HTTP sederhana jika masih berjalan.
$ mkdir -p img; cd img
$ wget https://github.com/googlecodelabs/google-maps-simple-store-locator/raw/master/src/img/icon_cafe.png
$ wget https://github.com/googlecodelabs/google-maps-simple-store-locator/raw/master/src/img/icon_patisserie.png
$ wget https://github.com/googlecodelabs/google-maps-simple-store-locator/raw/master/src/img/logo_cafe.png
$ wget https://github.com/googlecodelabs/google-maps-simple-store-locator/raw/master/src/img/logo_patisserie.png
  1. Lihat pratinjau pencari toko yang sudah selesai dengan menjalankan perintah berikut:.
$ python -m SimpleHTTPServer 8080

Saat memuat ulang pratinjau, Anda akan melihat tampilan seperti peta ini dengan gaya visual kustom, gambar penanda kustom, pemformatan jendela info yang lebih baik, dan gambar Street View untuk setiap lokasi:

3d8d13da126021dd.png

6. Mendapatkan input pengguna

Pengguna pencari toko biasanya ingin mengetahui toko mana yang paling dekat dengan posisi mereka atau alamat tempat mereka berencana memulai perjalanan. Tambahkan kotak penelusuran Place Autocomplete agar pengguna dapat memasukkan alamat titik awal dengan mudah. Place Autocomplete memberikan fungsi prediksi yang serupa dengan cara kerja Autocomplete di kotak penelusuran Google lainnya, tetapi prediksinya adalah semua Tempat di Google Maps Platform.

  1. Kembali untuk mengedit index.html guna menambahkan gaya visual untuk kotak penelusuran Autocomplete dan panel samping hasil yang terkait. Jangan lupa untuk mengganti kunci API jika Anda menempelkan kode lama.

index.html

<html>

<head>
  <title>Store Locator</title>
  <style>
    #map {
      height: 100%;
    }

    html,
    body {
      height: 100%;
      margin: 0;
      padding: 0;
    }

    /* Styling for Autocomplete search bar */
    #pac-card {
      background-color: #fff;
      border-radius: 2px 0 0 2px;
      box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
      box-sizing: border-box;
      font-family: Roboto;
      margin: 10px 10px 0 0;
      -moz-box-sizing: border-box;
      outline: none;
    }

    #pac-container {
      padding-top: 12px;
      padding-bottom: 12px;
      margin-right: 12px;
    }

    #pac-input {
      background-color: #fff;
      font-family: Roboto;
      font-size: 15px;
      font-weight: 300;
      margin-left: 12px;
      padding: 0 11px 0 13px;
      text-overflow: ellipsis;
      width: 400px;
    }

    #pac-input:focus {
      border-color: #4d90fe;
    }

    #title {
      color: #fff;
      background-color: #acbcc9;
      font-size: 18px;
      font-weight: 400;
      padding: 6px 12px;
    }

    .hidden {
      display: none;
    }

    /* Styling for an info pane that slides out from the left.
     * Hidden by default. */
    #panel {
      height: 100%;
      width: null;
      background-color: white;
      position: fixed;
      z-index: 1;
      overflow-x: hidden;
      transition: all .2s ease-out;
    }

    .open {
      width: 250px;
    }

    .place {
      font-family: 'open sans', arial, sans-serif;
      font-size: 1.2em;
      font-weight: 500;
      margin-block-end: 0px;
      padding-left: 18px;
      padding-right: 18px;
    }

    .distanceText {
      color: silver;
      font-family: 'open sans', arial, sans-serif;
      font-size: 1em;
      font-weight: 400;
      margin-block-start: 0.25em;
      padding-left: 18px;
      padding-right: 18px;
    }
  </style>
</head>

<body>
  <!-- The div to hold the map -->
  <div id="map"></div>

  <script src="app.js"></script>
  <script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap&solution_channel=GMP_codelabs_simplestorelocator_v1_a">
  </script>
</body>

</html>

Kotak penelusuran Autocomplete dan panel slideout awalnya tersembunyi hingga diperlukan.

  1. Sekarang, tambahkan widget Autocomplete ke peta di akhir fungsi initMap dalam app.js, tepat sebelum tanda kurung kurawal penutup.

app.js

  // Build and add the search bar
  const card = document.createElement('div');
  const titleBar = document.createElement('div');
  const title = document.createElement('div');
  const container = document.createElement('div');
  const input = document.createElement('input');
  const options = {
    types: ['address'],
    componentRestrictions: {country: 'gb'},
  };

  card.setAttribute('id', 'pac-card');
  title.setAttribute('id', 'title');
  title.textContent = 'Find the nearest store';
  titleBar.appendChild(title);
  container.setAttribute('id', 'pac-container');
  input.setAttribute('id', 'pac-input');
  input.setAttribute('type', 'text');
  input.setAttribute('placeholder', 'Enter an address');
  container.appendChild(input);
  card.appendChild(titleBar);
  card.appendChild(container);
  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);

  // Make the search bar into a Places Autocomplete search bar and select
  // which detail fields should be returned about the place that
  // the user selects from the suggestions.
  const autocomplete = new google.maps.places.Autocomplete(input, options);

  autocomplete.setFields(
      ['address_components', 'geometry', 'name']);

Kode ini membatasi saran Autocomplete untuk hanya menampilkan alamat (karena Place Autocomplete dapat mencocokkan nama bangunan dan lokasi administratif) dan membatasi alamat yang ditampilkan hanya kepada orang yang berada di Inggris Raya. Menambahkan spesifikasi opsional ini akan mengurangi jumlah karakter yang harus dimasukkan pengguna untuk mempersempit prediksi agar dapat menampilkan alamat yang mereka cari. Kemudian, kode ini memindahkan div Autocomplete yang telah Anda buat ke sudut kanan atas peta dan menentukan kolom mana yang harus ditampilkan tentang setiap Tempat dalam respons.

  1. Mulai ulang server dan muat ulang pratinjau Anda dengan menjalankan perintah berikut:
$ python -m SimpleHTTPServer 8080

Anda akan melihat widget Autocomplete di sudut kanan atas peta, yang menunjukkan alamat di Inggris Raya yang cocok dengan teks yang Anda ketik.

5163f34a03910187.png

Sekarang, Anda perlu mengatur kapan pengguna memilih prediksi dari widget Autocomplete dan menggunakan lokasi tersebut sebagai dasar untuk menghitung jarak ke toko Anda.

  1. Tambahkan kode berikut ke akhir initMap di app.js setelah kode yang baru saja Anda tempelkan.

app.js

 // Set the origin point when the user selects an address
  const originMarker = new google.maps.Marker({map: map});
  originMarker.setVisible(false);
  let originLocation = map.getCenter();

  autocomplete.addListener('place_changed', async () => {
    originMarker.setVisible(false);
    originLocation = map.getCenter();
    const place = autocomplete.getPlace();

    if (!place.geometry) {
      // User entered the name of a Place that was not suggested and
      // pressed the Enter key, or the Place Details request failed.
      window.alert('No address available for input: \'' + place.name + '\'');
      return;
    }

    // Recenter the map to the selected address
    originLocation = place.geometry.location;
    map.setCenter(originLocation);
    map.setZoom(9);
    console.log(place);

    originMarker.setPosition(originLocation);
    originMarker.setVisible(true);

    // Use the selected address as the origin to calculate distances
    // to each of the store locations
    const rankedStores = await calculateDistances(map.data, originLocation);
    showStoresList(map.data, rankedStores);

    return;
  });

Kode ini menambahkan pemroses sehingga saat pengguna mengklik salah satu saran, peta akan kembali ke pusat di alamat yang dipilih dan menetapkan tempat asal sebagai dasar penghitungan jarak Anda. Anda menerapkan penghitungan jarak pada langkah berikutnya.

7. Membuat daftar toko terdekat

Cara kerja Directions API mirip seperti pengalaman meminta rute di aplikasi Google Maps—memasukkan satu tempat asal dan satu tujuan untuk mendapatkan rute di antara kedua lokasi tersebut. Distance Matrix API menggunakan konsep ini lebih lanjut untuk mengidentifikasi pasangan optimal antara beberapa kemungkinan tempat asal dan beberapa kemungkinan tujuan berdasarkan waktu dan jarak perjalanan. Dalam hal ini, untuk membantu pengguna menemukan toko terdekat dengan alamat yang dipilih, Anda memberikan satu tempat asal dan array lokasi toko sebagai tujuan.

  1. Tambahkan fungsi baru ke app.js yang bernama calculateDistances.

app.js

async function calculateDistances(data, origin) {
  const stores = [];
  const destinations = [];

  // Build parallel arrays for the store IDs and destinations
  data.forEach((store) => {
    const storeNum = store.getProperty('storeid');
    const storeLoc = store.getGeometry().get();

    stores.push(storeNum);
    destinations.push(storeLoc);
  });

  // Retrieve the distances of each store from the origin
  // The returned list will be in the same order as the destinations list
  const service = new google.maps.DistanceMatrixService();
  const getDistanceMatrix =
    (service, parameters) => new Promise((resolve, reject) => {
      service.getDistanceMatrix(parameters, (response, status) => {
        if (status != google.maps.DistanceMatrixStatus.OK) {
          reject(response);
        } else {
          const distances = [];
          const results = response.rows[0].elements;
          for (let j = 0; j < results.length; j++) {
            const element = results[j];
            const distanceText = element.distance.text;
            const distanceVal = element.distance.value;
            const distanceObject = {
              storeid: stores[j],
              distanceText: distanceText,
              distanceVal: distanceVal,
            };
            distances.push(distanceObject);
          }

          resolve(distances);
        }
      });
    });

  const distancesList = await getDistanceMatrix(service, {
    origins: [origin],
    destinations: destinations,
    travelMode: 'DRIVING',
    unitSystem: google.maps.UnitSystem.METRIC,
  });

  distancesList.sort((first, second) => {
    return first.distanceVal - second.distanceVal;
  });

  return distancesList;
}

Fungsi ini memanggil Distance Matrix API menggunakan tempat asal yang dikirimkan sebagai satu tempat asal dan lokasi toko sebagai array tujuan. Kemudian, fungsi ini membuat array object yang menyimpan ID toko, jarak yang dinyatakan dalam string yang dapat dibaca manusia, jarak dalam meter sebagai nilai numerik, dan mengurutkan array.

Pengguna mengharapkan untuk melihat daftar toko yang diurutkan dari posisi yang terdekat hingga yang terjauh. Isi listingan panel samping untuk setiap toko menggunakan daftar yang ditampilkan dari fungsi calculateDistances untuk menginformasikan urutan tampilan toko.

  1. Tambahkan fungsi baru ke app.js yang bernama showStoresList.

app.js

function showStoresList(data, stores) {
  if (stores.length == 0) {
    console.log('empty stores');
    return;
  }

  let panel = document.createElement('div');
  // If the panel already exists, use it. Else, create it and add to the page.
  if (document.getElementById('panel')) {
    panel = document.getElementById('panel');
    // If panel is already open, close it
    if (panel.classList.contains('open')) {
      panel.classList.remove('open');
    }
  } else {
    panel.setAttribute('id', 'panel');
    const body = document.body;
    body.insertBefore(panel, body.childNodes[0]);
  }

  // Clear the previous details
  while (panel.lastChild) {
    panel.removeChild(panel.lastChild);
  }

  stores.forEach((store) => {
    // Add store details with text formatting
    const name = document.createElement('p');
    name.classList.add('place');
    const currentStore = data.getFeatureById(store.storeid);
    name.textContent = currentStore.getProperty('name');
    panel.appendChild(name);
    const distanceText = document.createElement('p');
    distanceText.classList.add('distanceText');
    distanceText.textContent = store.distanceText;
    panel.appendChild(distanceText);
  });

  // Open the panel
  panel.classList.add('open');

  return;
}
  1. Mulai ulang server dan muat ulang pratinjau Anda dengan menjalankan perintah berikut.
$ python -m SimpleHTTPServer 8080
  1. Terakhir, masukkan alamat di Inggris Raya ke kotak penelusuran Autocomplete lalu klik salah satu saran.

Peta akan menempatkan alamat tersebut di tengah dan sidebar akan muncul yang mencantumkan lokasi toko dalam urutan jarak dari alamat yang dipilih. Salah satu contohnya digambarkan sebagai berikut:

489628918395c3d0.png

8. Opsional: Menghosting halaman web Anda

Hingga titik ini, Anda hanya melihat peta saat aktif menjalankan server HTTP Python. Untuk melihat peta di luar sesi Cloud Shell yang aktif atau agar dapat membagikan URL peta Anda kepada orang lain, lihat cara menggunakan Cloud Storage untuk menghosting halaman web Anda. Cloud Storage adalah layanan web penyimpanan file online untuk menyimpan dan mengakses data di infrastruktur Google. Layanan ini menggabungkan performa dan skalabilitas Google Cloud dengan kemampuan berbagi dan keamanan yang canggih. Layanan ini juga menawarkan paket gratis, yang menjadikannya ideal untuk menghosting pencari toko sederhana Anda.

Dengan Cloud Storage, file disimpan dalam bucket, yang serupa dengan direktori di komputer Anda. Untuk menghosting halaman web, Anda harus membuat bucket terlebih dahulu. Anda harus memilih nama yang unik untuk bucket tersebut, mungkin dengan menggunakan nama Anda sebagai bagian dari nama bucket.

  1. Setelah Anda menentukan nama, jalankan perintah berikut di Cloud Shell:
$ gsutil mb gs://yourname-store-locator

gsutil adalah alat untuk berinteraksi dengan Cloud Storage. Perintah mb secara kreatif mengindikasikan "buat bucket". Untuk informasi selengkapnya tentang semua perintah yang tersedia, termasuk yang Anda gunakan, lihat alat gsutil.

Secara default, bucket dan file yang dihosting di Cloud Storage bersifat pribadi. Namun, untuk pencari toko, Anda ingin semua file bersifat publik agar dapat diakses oleh semua orang melalui internet. Anda dapat membuat setiap file bersifat publik setelah menguploadnya, tetapi hal ini merepotkan. Sebagai alternatif, Anda dapat menetapkan tingkat akses default untuk bucket yang Anda buat dan semua file yang diupload ke dalamnya akan mewarisi tingkat akses tersebut.

  1. Jalankan perintah berikut dengan mengganti yourname-store-locator dengan nama yang Anda pilih untuk bucket:
$ gsutil defacl ch -u AllUsers:R gs://yourname-store-locator
  1. Sekarang Anda dapat mengupload semua file dalam direktori saat ini (untuk saat ini hanya file index.html dan app.js) dengan perintah berikut:
$ gsutil -h "Cache-Control:no-cache" cp * gs://yourname-store-locator

Anda sekarang akan memiliki halaman web dengan peta online. URL untuk melihatnya adalah http://storage.googleapis.com/yourname-store-locator/index.html, sekali lagi dengan bagian yourname-store-locator diganti dengan nama bucket yang telah Anda pilih sebelumnya.

Melakukan pembersihan

Cara termudah untuk membersihkan semua resource yang dibuat dalam project ini adalah dengan menonaktifkan Google Cloud Project yang Anda buat di awal tutorial ini:

  • Buka Halaman Setelan di Cloud Console
  • Klik Pilih project.
  • Pilih project yang Anda buat di awal tutorial ini lalu klik Buka
  • Masukkan Project ID lalu klik Matikan.

9. Selamat

Selamat. Anda telah menyelesaikan codelab ini.

Yang telah Anda pelajari

Mempelajari lebih lanjut

Apa saja codelab lain yang ingin Anda lihat?

Visualisasi data pada peta Selengkapnya tentang cara menyesuaikan gaya peta saya Membuat interaksi 3D di peta

Apakah codelab yang Anda inginkan tidak tercantum di atas? Ajukan permintaan bersama masalah baru di sini.

Jika Anda ingin mempelajari kode lebih lanjut, lihat repositori kode sumber di https://github.com/googlecodelabs/google-maps-simple-store-locator.