Megosztás a következőn keresztül:


Oktatóanyag: Áruházkereső létrehozása az Azure Térképek használatával

Ez az oktatóanyag végigvezeti egy egyszerű tárolókereső Azure-Térképek használatával történő létrehozásának folyamatán.

Az oktatóanyag segítségével megtanulhatja a következőket:

  • Hozzon létre egy új weblapot az Azure Map Control API használatával.
  • Egyéni adatokat tölthet be egy fájlból, és megjelenítheti egy térképen.
  • Az Azure Térképek Search szolgáltatás használatával kereshet meg egy címet, vagy megadhat egy lekérdezést.
  • Kérje le a felhasználó helyét a böngészőből, és jelenítse meg a térképen.
  • Több réteg kombinálásával egyéni szimbólumokat hozhat létre a térképen.
  • Fürt adatpontjai.
  • Nagyítási vezérlők hozzáadása a térképhez.

Előfeltételek

Feljegyzés

Az Azure Térképek-hitelesítéssel kapcsolatos további információkért lásd az Azure Térképek hitelesítésének kezelését.

Mintakód

Ez az oktatóanyag bemutatja, hogyan hozhat létre áruházkeresőt egy Contoso Coffee nevű fiktív vállalat számára, valamint tippeket nyújt az áruházkereső további funkciókkal való kibővítéséhez.

Az oktatóanyagban létrehozott élő minta megtekintéséhez tekintse meg a Simple Store Locatort az Azure Térképek Kódminták webhelyén.

Az oktatóanyag egyszerűbb követéséhez és használatához töltse le a következő erőforrásokat:

Az Áruház keresőfunkciói

Ez a szakasz az oktatóanyagban létrehozott Contoso Coffee Store keresőalkalmazásban bemutatott Azure Térképek funkciókat sorolja fel.

Felhasználói felületi funkciók

  • Egy áruház emblémája a fejlécen
  • Pásztázást és nagyítást támogató térkép
  • A Saját hely gomb a felhasználó aktuális helyére való kereséshez.
  • Lapelrendezés, amely az eszközök képernyője szélessége alapján módosul
  • Keresőmező és keresési gomb

Funkciófunkciók

  • A keypress keresőmezőhöz hozzáadott esemény akkor aktiválja a keresést, amikor a felhasználó lenyomja az Enter billentyűt.
  • A térkép áthelyezésekor a térkép közepétől az egyes helyek közötti távolság újraszámításra kerül. Az eredmények listája frissül, hogy a térkép tetején a legközelebbi helyek jelenjenek meg.
  • Amikor a felhasználó kiválaszt egy találatot az eredmények listájában, a térkép középre van állítva a kijelölt hely felett, és a hely adatai megjelennek egy előugró ablakban.
  • Amikor a felhasználó kiválaszt egy adott helyet, a térkép elindít egy előugró ablakot.
  • Amikor a felhasználó kicsinyít, a helyek fürtökbe vannak csoportosítva. Minden fürtöt egy kör jelöl, amelynek a körön belül egy száma van. A fürtök a nagyítási szint módosításakor egymástól elkülönülnek.
  • A fürt kiválasztása két szinten nagyít a térképen, és középre igazítja a fürt helyét.

Áruház lokátorának kialakítása

Az alábbi képernyőképen a Contoso Coffee Store keresőalkalmazás általános elrendezése látható. Az élő minta megtekintéséhez és használatához tekintse meg a Simple Store Locator mintaalkalmazást az Azure Térképek Kódminták webhelyén.

Képernyőkép a Contoso Coffee Store-lokátor Azure Térképek mintaalkalmazásról.

Az áruházkereső hasznosságának maximalizálása érdekében rugalmas elrendezést biztosítunk, amely 700 képpontnál kisebb képernyőszélességet biztosít. A rugalmas elrendezés megkönnyíti a tárolókereső használatát egy kis képernyőn, például mobileszközön. Az alábbi képernyőképen a kis képernyős elrendezés mintája látható:

Képernyőkép arról, hogy a Contoso Coffee Store keresőalkalmazás hogyan néz ki mobileszközön.

Az áruház helyadatkészletének létrehozása

Ez a szakasz bemutatja, hogyan hozhat létre adatkészletet a térképen megjeleníteni kívánt áruházakból. A Contoso Kávékereső adatkészlete egy Excel-munkafüzetben jön létre. Az adatkészlet 10 213 Contoso Coffee kávézót tartalmaz, amelyek kilenc országban vagy régióban találhatók: a Egyesült Államok, Kanada, az Egyesült Királyság, Franciaország, Németország, Olaszország, Hollandia, Dánia és Spanyolország. Íme egy képernyőkép az adatok megjelenéséről:

Képernyőkép az Áruházkereső adatairól egy Excel-munkafüzetben.

Töltse le a Contoso Coffee locator mintaalkalmazás teljes adatkészletét tartalmazó Excel-fájlt az Azure Térképek gitHub-kódminták adattárának adatmappájából.

Az adatok fenti képernyőképén a következő megfigyeléseket végezhetjük el:

  • A helyadatokat a következő hat oszlop tárolja: AddressLine, City, Municipality (county), Rendszergazda Division (state/province), PostCode (irányítószám) és Country.
  • A Szélesség és hosszúság oszlopok tartalmazzák az egyes Contoso Kávéhelyek koordinátáit. Ha nem rendelkezik koordináta-információkkal, a Search szolgáltatás segítségével meghatározhatja a hely koordinátáit.
  • Néhány más oszlop a kávézókhoz kapcsolódó metaadatokat tartalmaz: telefonszámot, logikai oszlopokat, valamint 24 órás formátumban a boltok nyitvatartási és záróidejét. A logikai oszlopok a Wi-Fi és a kerekesszék akadálymentesítésére használhatók. Létrehozhat saját oszlopokat, amelyek a helyadatok szempontjából relevánsabb metaadatokat tartalmaznak.

Feljegyzés

Az Azure Térképek a Spherical Mercator "EPSG:3857" vetületében jeleníti meg az adatokat, de a WGS84-objektumot használó "EPSG:4326" formátumban olvassa be az adatokat.

A Contoso Kávézó lokátor adatkészletének betöltése

A Contoso Kávézó kereső adatkészlete kicsi, így tabulátorral tagolt szövegfájllá alakítható, amelyet a böngésző letölt az alkalmazás betöltésekor.

Tipp.

Ha az adathalmaz túl nagy az ügyfél letöltéséhez, vagy gyakran frissül, érdemes lehet az adathalmazt egy adatbázisban tárolnia. Miután betöltötte az adatokat egy adatbázisba, beállíthat egy webszolgáltatást, amely fogadja az adatok lekérdezéseit, majd elküldi az eredményeket a felhasználó böngészőjének.

Adatok átalakítása tabulátorral tagolt szövegfájllá

Ha a Contoso Kávézó helyadatait egy Excel-munkafüzetből tabulátorral tagolt szövegfájllá szeretné konvertálni:

  1. Töltse le az Excel-munkafüzetet ContosoCoffee.xlsx , és nyissa meg az Excelben.

  2. Válassza a Fájl > mentése másként...lehetőséget.

  3. A Mentés típusként legördülő listában válassza a Szöveg (Tabulátorral tagolt)(*.txt) lehetőséget.

  4. Nevezze el a ContosoCoffee fájlt.

Képernyőkép a Mentés típusként párbeszédpanelről.

Ha a szövegfájlt Jegyzettömb nyitja meg, az a következőhöz hasonló:

Képernyőkép egy Jegyzettömb fájlról, amely egy tabulátorral tagolt adatkészletet jelenít meg.

A projekt előkészítése

  1. Nyissa meg a Visual Studio Code-ot vagy a választott fejlesztői környezetet.

  2. Válassza a Fájl > megnyitása munkaterület...lehetőséget.

  3. Hozzon létre egy ContosoCoffee nevű új mappát.

  4. Válassza a ContosoCoffee lehetőséget az explorerben.

  5. Hozza létre a következő három fájlt, amelyek meghatározzák az alkalmazás elrendezését, stílusát és logikáját:

    • Index.html
    • index.css
    • index.js
  6. Hozzon létre egy névvel ellátott mappát.

  7. Adja hozzá az Excel-munkafüzetből korábban létrehozott ContosoCoffee.txt fájlt ContosoCoffee.xlsx az adatmappához.

  8. Hozzon létre egy másik, képek nevű mappát.

  9. Ha még nem tette meg, töltse le a 10 térképképet a GitHub-adattár képkönyvtárából, és vegye fel őket a képek mappájába.

    A munkaterület mappájának most az alábbi képernyőképhez hasonlóan kell kinéznie:

    Képernyőkép a Contoso Coffee könyvtárban található képek mappáról.

A HTML létrehozása

A HTML létrehozása:

  1. Adja hozzá a következő meta címkéket a head index.html:

    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="IE=Edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    
  2. Hivatkozások hozzáadása az Azure Térképek webvezérlő JavaScript- és CSS-fájljaihoz:

    <!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
    <link rel="stylesheet" href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.css" type="text/css">
    <script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.js"></script>
    
  3. Adjon hozzá hivatkozásokat index.js és index.css.

    <!-- Add references to the store locator JavaScript and CSS files. -->
    <link rel="stylesheet" href="index.css" type="text/css">
    <script src="index.js"></script>
    
  4. A dokumentum törzsében adjon hozzá egy címkét header . A címkén header belül adja hozzá az emblémát és a vállalat nevét.

    <header>
        <img src="images/Logo.png" />
        <span>Contoso Coffee</span>
    </header>
    
  5. Vegyen fel egy címkét main , és hozzon létre egy keresőmezőt és egy keresési gombot tartalmazó keresőmezőt. Emellett adjon meg div hivatkozásokat a térképhez, a listapanelhez és a Saját hely GPS gombjához.

    <main>
        <div class="searchPanel">
            <div>
                <input id="searchTbx" type="search" placeholder="Find a store" />
                <button id="searchBtn" title="Search"></button>
            </div>
        </div>
        <div id="listPanel"></div>
        <div id="myMap"></div>
        <button id="myLocationBtn" title="My Location"></button>
    </main>
    

Ha végzett, index.html úgy kell kinéznie, mint a Simple Store Locator.html az oktatóanyag mintakódjában.

A CSS-stílusok meghatározása

A következő lépés a CSS-stílusok meghatározása. A CSS-stílusok határozzák meg az alkalmazás összetevőinek kialakítását és az alkalmazás megjelenését.

  1. Nyissa meg a index.css.

  2. Adja hozzá a következő css-kódot:

    Feljegyzés

    A @media stílus alternatív stílusbeállításokat határoz meg, ha a képernyő szélessége kisebb, mint 700 képpont.

     html, body {
         padding: 0;
         margin: 0;
         font-family: Gotham, Helvetica, sans-serif;
         overflow-x: hidden;
     } 
    
     header {
         width: calc(100vw - 10px);
         height: 30px;
         padding: 15px 0 20px 20px;
         font-size: 25px;
         font-style: italic;
         font-family: "Comic Sans MS", cursive, sans-serif;
         line-height: 30px;
         font-weight: bold;
         color: white;
         background-color: #007faa;
     }
    
     header span {
         vertical-align: middle;
     }
    
     header img {
         height: 30px;
         vertical-align: middle;
     }
    
     .searchPanel {
         position: relative;
         width: 350px;
     }
    
     .searchPanel div {
         padding: 20px;
     }
    
     .searchPanel input {
         width: calc(100% - 50px);
         font-size: 16px;
         border: 0;
         border-bottom: 1px solid #ccc;
     }
    
     #listPanel {
         position: absolute;
         top: 135px;
         left: 0px;
         width: 350px;
         height: calc(100vh - 135px);
         overflow-y: auto;
     }
    
     #myMap { 
         position: absolute;
         top: 65px;
         left: 350px;
         width: calc(100vw - 350px);
         height: calc(100vh - 65px);
     }
    
     .statusMessage {
         margin: 10px;
     }
    
     #myLocationBtn, #searchBtn {
         margin: 0;
         padding: 0;
         border: none;
         border-collapse: collapse;
         width: 32px;
         height: 32px; 
         text-align: center;
         cursor: pointer;
         line-height: 32px;
         background-repeat: no-repeat;
         background-size: 20px;
         background-position: center center;
         z-index: 200;
     }
    
     #myLocationBtn {
         position: absolute;
         top: 150px;
         right: 10px;
         box-shadow: 0px 0px 4px rgba(0,0,0,0.16);
         background-color: white;
         background-image: url("images/GpsIcon.png");
     }
    
     #myLocationBtn:hover {
         background-image: url("images/GpsIcon-hover.png");
     }
    
     #searchBtn {
         background-color: transparent;
         background-image: url("images/SearchIcon.png");
     }
    
     #searchBtn:hover {
         background-image: url("images/SearchIcon-hover.png");
     }
    
     .listItem {
         height: 50px;
         padding: 20px;
         font-size: 14px;
     }
    
     .listItem:hover {
         cursor: pointer;
         background-color: #f1f1f1;
     }
    
     .listItem-title {
         color: #007faa;
         font-weight: bold;
     }
    
     .storePopup {
         min-width: 150px;
     }
    
     .storePopup .popupTitle {
         border-top-left-radius: 4px;
         border-top-right-radius: 4px;
         padding: 8px;
         height: 30px;
         background-color: #007faa;
         color: white;
         font-weight: bold;
     }
    
     .storePopup .popupSubTitle {
         font-size: 10px;
         line-height: 12px;
     }
    
     .storePopup .popupContent {
         font-size: 11px;
         line-height: 18px;
         padding: 8px;
     }
    
     .storePopup img {
         vertical-align:middle;
         height: 12px;
         margin-right: 5px;
     }
    
     /* Adjust the layout of the page when the screen width is fewer than 700 pixels. */
     @media screen and (max-width: 700px) {
         .searchPanel {
             width: 100vw;
         }
    
         #listPanel {
             top: 385px;
             width: 100%;
             height: calc(100vh - 385px);
         }
    
         #myMap {
             width: 100vw;
             height: 250px;
             top: 135px;
             left: 0px;
         }
    
         #myLocationBtn {
             top: 220px;
         }
     }
    
     .mapCenterIcon {
         display: block;
         width: 10px;
         height: 10px;
         border-radius: 50%;
         background: orange;
         border: 2px solid white;
         cursor: pointer;
         box-shadow: 0 0 0 rgba(0, 204, 255, 0.4);
         animation: pulse 3s infinite;
     }
    
     @keyframes pulse {
         0% {
             box-shadow: 0 0 0 0 rgba(0, 204, 255, 0.4);
         }
    
         70% {
             box-shadow: 0 0 0 50px rgba(0, 204, 255, 0);
         }
    
         100% {
             box-shadow: 0 0 0 0 rgba(0, 204, 255, 0);
         }
     }
    

Ha ezen a ponton futtatja az alkalmazást, megjelenik a fejléc, a keresőmező és a keresés gomb. A térkép azonban nem látható, mert még nincs betöltve. Ha megpróbál keresést végezni, semmi sem történik. A következő szakasz az áruházkereső összes funkciójának eléréséhez szükséges JavaScript-logika hozzáadását ismerteti.

JavaScript-kód hozzáadása

A Contoso Kávézó keresőalkalmazás JavaScript-kódja a következő folyamatokat teszi lehetővé:

  1. Hozzáad egy eseményfigyelőtready, amely várja meg, amíg a lap betöltési folyamata befejeződött. Amikor az oldal betöltése befejeződött, az eseménykezelő további eseményfigyelőket hoz létre a térkép betöltésének figyeléséhez, és funkcióval adhatja meg a keresést és a Saját hely gombokat.

  2. Amikor a felhasználó kiválasztja a keresési gombot, vagy begépel egy helyet a keresőmezőbe, majd lenyomja az Enter billentyűt, megkezdődik egy homályos keresés a felhasználó lekérdezésére. A kód az ország/régió ISO 2 értékeinek tömbjében adja át azt a countrySet lehetőséget, hogy a keresési eredményeket ezekre az országokra/régiókra korlátozza. Az országok/régiók keresésre való korlátozása növeli a visszaadott eredmények pontosságát.

  3. A keresés befejezése után a rendszer az első helyeredményt használja a térkép középpontjában. Amikor a felhasználó kiválasztja a Saját hely gombot, a kód lekéri a felhasználó helyét a böngészőbe beépített HTML5 Geolocation API használatával. A hely lekérése után a kód középre igazítja a térképet a felhasználó helyére.

A JavaScript hozzáadása:

  1. Nyissa meg a index.js.

  2. Globális beállítások hozzáadása a beállítások könnyebb frissítéséhez. Adja meg a térkép, az előugró ablak, az adatforrás, az ikonréteg és a HTML-jelölő változóit. Állítsa be a HTML-jelölőt úgy, hogy a keresési terület középpontját jelezze. És definiálja az Azure Térképek keresési szolgáltatás ügyfélpéldányát.

    //The maximum zoom level to cluster data point data on the map.
    var maxClusterZoomLevel = 11;
    
    //The URL to the store location data.
    var storeLocationDataUrl = 'data/ContosoCoffee.txt';
    
    //The URL to the icon image. 
    var iconImageUrl = 'images/CoffeeIcon.png';
    
    //An array of country region ISO2 values to limit searches to.
    var countrySet = ['US', 'CA', 'GB', 'FR','DE','IT','ES','NL','DK'];      
    
    //
    var map, popup, datasource, iconLayer, centerMarker;
    
    // Used in function updateListItems
    var listItemTemplate = '<div class="listItem" onclick="itemSelected(\'{id}\')"><div class="listItem-title">{title}</div>{city}<br />Open until {closes}<br />{distance} miles away</div>';
    
    
  3. Adja hozzá a következő inicializálási kódot. Mindenképpen cserélje le <Your Azure Maps Key> az Azure Térképek előfizetési kulcsára.

    Tipp.

    Előugró ablakok használata esetén a legjobb, ha egyetlen Popup példányt hoz létre, és a tartalom és a hely frissítésével újra felhasználja a példányt. A kódhoz hozzáadott összes Popuppéldány esetében a rendszer több DOM-elemet ad hozzá a laphoz. Minél több DOM-elem található egy lapon, annál több dolgot kell nyomon követnie a böngészőnek. Ha túl sok elem van, előfordulhat, hogy a böngésző lassú lesz.

    
    function initialize() {
        //Initialize a map instance.
        map = new atlas.Map('myMap', {
            center: [-90, 40],
            zoom: 2,
    
            //Add your Azure Maps subscription key to the map SDK.
            authOptions: {
                authType: 'subscriptionKey',
                subscriptionKey: '<Your Azure Maps Key>'
            }
        });
    
        //Create a pop-up window, but leave it closed so we can update it and display it later.
        popup = new atlas.Popup();
    
        //If the user selects the search button, geocode the value the user passed in.
        document.getElementById('searchBtn').onclick = performSearch;
    
        //If the user presses Enter in the search box, perform a search.
        document.getElementById('searchTbx').onkeyup = function(e) {
            if (e.keyCode === 13) {
                performSearch();
            }
        };
    
        //If the user selects the My Location button, use the Geolocation API to get the user's location. Center and zoom the map on that location.
        document.getElementById('myLocationBtn').onclick = setMapToUserLocation;
    
        //Wait until the map resources are ready.
        map.events.add('ready', function() {
    
            //Add your maps post load functionality.
    
        });
    }
    
    function performSearch() {
        var query = document.getElementById('searchTbx').value;
        //Pass in the array of country/region ISO2 for which we want to limit the search to.
        var url = `https://atlas.microsoft.com/search/fuzzy/json?api-version=1.0&countrySet=${countrySet}&query=${query}&view=Auto`;
    
        //Perform a fuzzy search on the users query.
        fetch(url, {
            headers: {
                "Subscription-Key": map.authentication.getToken()
            }
        })
        .then((response) => response.json())
        .then((response) => {
            if (Array.isArray(response.results) && response.results.length > 0) {
                var result = response.results[0];
                var bbox = [
                    result.viewport.topLeftPoint.lon,
                    result.viewport.btmRightPoint.lat,
                    result.viewport.btmRightPoint.lon,
                    result.viewport.topLeftPoint.lat
                ];
                //Set the camera to the bounds of the first result.
                map.setCamera({
                    bounds: bbox,
                    padding: 40
                });
            } else {
                document.getElementById('listPanel').innerHTML = '<div class="statusMessage">Unable to find the location you searched for.</div>';
            }
        });
    }
    
    function setMapToUserLocation() {
        //Request the user's location.
        navigator.geolocation.getCurrentPosition(function(position) {
            //Convert the geolocation API position into a longitude/latitude position value the map can understand and center the map over it.
            map.setCamera({
                center: [position.coords.longitude, position.coords.latitude],
                zoom: maxClusterZoomLevel + 1
            });
        }, function(error) {
            //If an error occurs when trying to access the users position information, display an error message.
            switch (error.code) {
                case error.PERMISSION_DENIED:
                    alert('User denied the request for geolocation.');
                    break;
                case error.POSITION_UNAVAILABLE:
                    alert('Position information is unavailable.');
                    break;
                case error.TIMEOUT:
                    alert('The request to get user position timed out.');
                    break;
                case error.UNKNOWN_ERROR:
                    alert('An unknown error occurred.');
                    break;
            }
        });
    }
    
    //Initialize the application when the page is loaded.
    window.onload = initialize;
    
  4. A térkép eseménykezelőjében ready adjon hozzá egy nagyítási vezérlőt és egy HTML-jelölőt a keresési terület középpontjának megjelenítéséhez.

    //Add a zoom control to the map.
    map.controls.add(new atlas.control.ZoomControl(), {
        position: 'top-right'
    });
    
    //Add an HTML marker to the map to indicate the center to use for searching.
    centerMarker = new atlas.HtmlMarker({
        htmlContent: '<div class="mapCenterIcon"></div>',
        position: map.getCamera().center
    });
    
    map.markers.add(centerMarker);
    
  5. A térkép eseménykezelőjében ready adjon hozzá egy adatforrást. Ezután hívjon meg egy hívást az adathalmaz betöltésére és elemzésére. Engedélyezze a fürtözést az adatforráson. A fürtözés az adatforrásokon átfedésben lévő pontokat fed egy fürtben. Ahogy a felhasználó nagyít, a fürtök különálló pontokra különülnek el. Ez a viselkedés jobb felhasználói élményt nyújt, és javítja a teljesítményt.

    //Create a data source, add it to the map, and then enable clustering.
    datasource = new atlas.source.DataSource(null, {
        cluster: true,
        clusterMaxZoom: maxClusterZoomLevel - 1
    });
    
    map.sources.add(datasource);
    
    //Load all the store data now that the data source has been defined.  
    loadStoreData();
    
  6. Miután az adathalmaz betöltődött a térkép eseménykezelőjében ready , definiáljon rétegeket az adatok megjelenítéséhez. A buborékréteg fürtözött adatpontokat jelenít meg. A szimbólumréteg a buborékréteg fölött jeleníti meg az egyes fürtökben lévő pontok számát. A második szimbólumréteg egy egyéni ikont jelenít meg a térkép egyes helyeihez.

    A buborék- és ikonrétegek felvétele mouseover és mouseout eseményei az egérmutató módosításához, amikor a felhasználó egy fürtre vagy ikonra mutat a térképen. click Esemény hozzáadása a fürt buborékrétegéhez. Ez az click esemény két szintet nagyít a térképen, és egy fürtre középre igazítja a térképet, amikor a felhasználó kiválaszt egy fürtöt. Esemény hozzáadása click az ikonréteghez. Ez az click esemény egy előugró ablakot jelenít meg, amely egy kávézó részleteit jeleníti meg, amikor a felhasználó kiválaszt egy adott hely ikont. Adjon hozzá egy eseményt a térképhez, amely figyeli, hogy mikor fejeződik be a térkép áthelyezése. Ha az esemény aktiválódik, frissítse a listapanel elemeit.

    //Create a bubble layer to render clustered data points.
    var clusterBubbleLayer = new atlas.layer.BubbleLayer(datasource, null, {
        radius: 12,
        color: '#007faa',
        strokeColor: 'white',
        strokeWidth: 2,
        filter: ['has', 'point_count'] //Only render data points that have a point_count property; clusters have this property.
    });
    
    //Create a symbol layer to render the count of locations in a cluster.
    var clusterLabelLayer = new atlas.layer.SymbolLayer(datasource, null, {
        iconOptions: {
            image: 'none' //Hide the icon image.
        },
    
        textOptions: {
            textField: ['get', 'point_count_abbreviated'],
            size: 12,
            font: ['StandardFont-Bold'],
            offset: [0, 0.4],
            color: 'white'
        }
    });
    
    map.layers.add([clusterBubbleLayer, clusterLabelLayer]);
    
    //Load a custom image icon into the map resources.
    map.imageSprite.add('myCustomIcon', iconImageUrl).then(function() {
    
       //Create a layer to render a coffee cup symbol above each bubble for an individual location.
       iconLayer = new atlas.layer.SymbolLayer(datasource, null, {
           iconOptions: {
               //Pass in the ID of the custom icon that was loaded into the map resources.
               image: 'myCustomIcon',
    
               //Optionally, scale the size of the icon.
               font: ['SegoeUi-Bold'],
    
               //Anchor the center of the icon image to the coordinate.
               anchor: 'center',
    
               //Allow the icons to overlap.
               allowOverlap: true
           },
    
           filter: ['!', ['has', 'point_count']] //Filter out clustered points from this layer.
       });
    
       map.layers.add(iconLayer);
    
       //When the mouse is over the cluster and icon layers, change the cursor to a pointer.
       map.events.add('mouseover', [clusterBubbleLayer, iconLayer], function() {
           map.getCanvasContainer().style.cursor = 'pointer';
       });
    
       //When the mouse leaves the item on the cluster and icon layers, change the cursor back to the default (grab).
       map.events.add('mouseout', [clusterBubbleLayer, iconLayer], function() {
           map.getCanvasContainer().style.cursor = 'grab';
       });
    
       //Add a click event to the cluster layer. When the user selects a cluster, zoom into it by two levels.  
       map.events.add('click', clusterBubbleLayer, function(e) {
           map.setCamera({
               center: e.position,
               zoom: map.getCamera().zoom + 2
           });
       });
    
       //Add a click event to the icon layer and show the shape that was selected.
       map.events.add('click', iconLayer, function(e) {
           showPopup(e.shapes[0]);
       });
    
       //Add an event to monitor when the map has finished rendering.
       map.events.add('render', function() {
           //Update the data in the list.
           updateListItems();
       });
    });
    
  7. Amikor a kávézó adatkészletére van szükség, először le kell tölteni. A letöltés után a fájlt sorokra kell felosztani. Az első sor tartalmazza a fejléc adatait. A kód könnyebb követéséhez az élőfejet egy objektumba elemeljük, amellyel megkereshetjük az egyes tulajdonságok cellaindexét. Az első sor után hurkolja át a többi sort, és hozzon létre egy pontfunkciót. Adja hozzá a pont funkciót az adatforráshoz. Végül frissítse a listapanelt.

    function loadStoreData() {
    
    //Download the store location data.
    fetch(storeLocationDataUrl)
        .then(response => response.text())
        .then(function(text) {
    
            //Parse the tab-delimited file data into GeoJSON features.
            var features = [];
    
            //Split the lines of the file.
            var lines = text.split('\n');
    
            //Grab the header row.
            var row = lines[0].split('\t');
    
            //Parse the header row and index each column to make the code for parsing each row easier to follow.
            var header = {};
            var numColumns = row.length;
            for (var i = 0; i < row.length; i++) {
                header[row[i]] = i;
            }
    
            //Skip the header row and then parse each row into a GeoJSON feature.
            for (var i = 1; i < lines.length; i++) {
                row = lines[i].split('\t');
    
                //Ensure that the row has the correct number of columns.
                if (row.length >= numColumns) {
    
                    features.push(new atlas.data.Feature(new atlas.data.Point([parseFloat(row[header['Longitude']]), parseFloat(row[header['Latitude']])]), {
                        AddressLine: row[header['AddressLine']],
                        City: row[header['City']],
                        Municipality: row[header['Municipality']],
                        AdminDivision: row[header['AdminDivision']],
                        Country: row[header['Country']],
                        PostCode: row[header['PostCode']],
                        Phone: row[header['Phone']],
                        StoreType: row[header['StoreType']],
                        IsWiFiHotSpot: (row[header['IsWiFiHotSpot']].toLowerCase() === 'true') ? true : false,
                        IsWheelchairAccessible: (row[header['IsWheelchairAccessible']].toLowerCase() === 'true') ? true : false,
                        Opens: parseInt(row[header['Opens']]),
                        Closes: parseInt(row[header['Closes']])
                    }));
                }
            }
    
            //Add the features to the data source.
            datasource.add(new atlas.data.FeatureCollection(features));
    
            //Initially, update the list items.
            updateListItems();
        });
    }
    
  8. A listapanel frissítésekor a rendszer kiszámítja a távolságot. Ez a távolság a térkép közepétől az aktuális térképnézetben található összes pontfunkcióig van. A funkciók ezután távolság szerint vannak rendezve. A rendszer HTML-fájlt hoz létre, hogy megjelenítse az egyes helyeket a listapanelen.

    var listItemTemplate = '<div class="listItem" onclick="itemSelected(\'{id}\')"><div class="listItem-title">{title}</div>{city}<br />Open until {closes}<br />{distance} miles away</div>';
    
    function updateListItems() {
        //Hide the center marker.
        centerMarker.setOptions({
            visible: false
        });
    
        //Get the current camera and view information for the map.
        var camera = map.getCamera();
        var listPanel = document.getElementById('listPanel');
    
        //Check to see if the user is zoomed out a substantial distance. If they are, tell them to zoom in and to perform a search or select the My Location button.
        if (camera.zoom < maxClusterZoomLevel) {
            //Close the pop-up window; clusters might be displayed on the map.  
            popup.close(); 
            listPanel.innerHTML = '<div class="statusMessage">Search for a location, zoom the map, or select the My Location button to see individual locations.</div>';
        } else {
            //Update the location of the centerMarker property.
            centerMarker.setOptions({
                position: camera.center,
                visible: true
            });
    
            //List the ten closest locations in the side panel.
            var html = [], properties;
    
            /*
            Generating HTML for each item that looks like this:
            <div class="listItem" onclick="itemSelected('id')">
                <div class="listItem-title">1 Microsoft Way</div>
                Redmond, WA 98052<br />
                Open until 9:00 PM<br />
                0.7 miles away
            </div>
            */
    
            //Get all the shapes that have been rendered in the bubble layer. 
            var data = map.layers.getRenderedShapes(map.getCamera().bounds, [iconLayer]);
    
            //Create an index of the distances of each shape.
            var distances = {};
    
            data.forEach(function (shape) {
                if (shape instanceof atlas.Shape) {
    
                    //Calculate the distance from the center of the map to each shape and store in the index. Round to 2 decimals.
                    distances[shape.getId()] = Math.round(atlas.math.getDistanceTo(camera.center, shape.getCoordinates(), 'miles') * 100) / 100;
                }
            });
    
            //Sort the data by distance.
            data.sort(function (x, y) {
                return distances[x.getId()] - distances[y.getId()];
            });
    
            data.forEach(function(shape) {
                properties = shape.getProperties();
                html.push('<div class="listItem" onclick="itemSelected(\'', shape.getId(), '\')"><div class="listItem-title">',
                properties['AddressLine'],
                '</div>',
                //Get a formatted addressLine2 value that consists of City, Municipality, AdminDivision, and PostCode.
                getAddressLine2(properties),
                '<br />',
    
                //Convert the closing time to a format that is easier to read.
                getOpenTillTime(properties),
                '<br />',
    
                //Get the distance of the shape.
                distances[shape.getId()],
                ' miles away</div>');
            });
    
            listPanel.innerHTML = html.join('');
    
            //Scroll to the top of the list panel in case the user has scrolled down.
            listPanel.scrollTop = 0;
        }
    }
    
    //This converts a time that's in a 24-hour format to an AM/PM time or noon/midnight string.
    function getOpenTillTime(properties) {
        var time = properties['Closes'];
        var t = time / 100;
        var sTime;
    
        if (time === 1200) {
            sTime = 'noon';
        } else if (time === 0 || time === 2400) {
            sTime = 'midnight';
        } else {
            sTime = Math.round(t) + ':';
    
            //Get the minutes.
            t = (t - Math.round(t)) * 100;
    
            if (t === 0) {
                sTime += '00';
            } else if (t < 10) {
                sTime += '0' + t;
            } else {
                sTime += Math.round(t);
            }
    
            if (time < 1200) {
                sTime += ' AM';
            } else {
                sTime += ' PM';
            }
        }
    
        return 'Open until ' + sTime;
    }
    
    //Create an addressLine2 string that contains City, Municipality, AdminDivision, and PostCode.
    function getAddressLine2(properties) {
        var html = [properties['City']];
    
        if (properties['Municipality']) {
            html.push(', ', properties['Municipality']);
        }
    
        if (properties['AdminDivision']) {
            html.push(', ', properties['AdminDivision']);
        }
    
        if (properties['PostCode']) {
            html.push(' ', properties['PostCode']);
        }
    
        return html.join('');
    }
    
  9. Amikor a felhasználó kiválaszt egy elemet a listapanelen, a rendszer lekéri az adatforrásból azt az alakzatot, amelyhez az elem kapcsolódik. Létrejön egy előugró ablak, amely az alakzatban tárolt tulajdonságadatokon alapul. A térkép középen van az alakzat felett. Ha a térkép kisebb, mint 700 képpont széles, a térképnézet el van tolva, hogy az előugró ablak látható legyen.

    //When a user selects a result in the side panel, look up the shape by its ID value and display the pop-up window.
    function itemSelected(id) {
        //Get the shape from the data source by using its ID.  
        var shape = datasource.getShapeById(id);
        showPopup(shape);
    
        //Center the map over the shape on the map.
        var center = shape.getCoordinates();
        var offset;
    
        //If the map is fewer than 700 pixels wide, then the layout is set for small screens.
        if (map.getCanvas().width < 700) {
            //When the map is small, offset the center of the map relative to the shape so that there is room for the popup to appear.
            offset = [0, -80];
        }
    
        map.setCamera({
            center: center,
            centerOffset: offset
        });
    }
    
    function showPopup(shape) {
        var properties = shape.getProperties();
    
        /* Generating HTML for the pop-up window that looks like this:
    
            <div class="storePopup">
                <div class="popupTitle">
                    3159 Tongass Avenue
                    <div class="popupSubTitle">Ketchikan, AK 99901</div>
                </div>
                <div class="popupContent">
                    Open until 22:00 PM<br/>
                    <img title="Phone Icon" src="images/PhoneIcon.png">
                    <a href="tel:1-800-XXX-XXXX">1-800-XXX-XXXX</a>
                    <br>Amenities:
                    <img title="Wi-Fi Hotspot" src="images/WiFiIcon.png">
                    <img title="Wheelchair Accessible" src="images/WheelChair-small.png">
                </div>
            </div>
        */
    
         //Calculate the distance from the center of the map to the shape in miles, round to 2 decimals.
        var distance = Math.round(atlas.math.getDistanceTo(map.getCamera().center, shape.getCoordinates(), 'miles') * 100)/100;
    
        var html = ['<div class="storePopup">'];
        html.push('<div class="popupTitle">',
            properties['AddressLine'],
            '<div class="popupSubTitle">',
            getAddressLine2(properties),
            '</div></div><div class="popupContent">',
    
            //Convert the closing time to a format that's easier to read.
            getOpenTillTime(properties),
    
            //Add the distance information.  
            '<br/>', distance,
            ' miles away',
            '<br /><img src="images/PhoneIcon.png" title="Phone Icon"/><a href="tel:',
            properties['Phone'],
            '">',  
            properties['Phone'],
            '</a>'
        );
    
        if (properties['IsWiFiHotSpot'] || properties['IsWheelchairAccessible']) {
            html.push('<br/>Amenities: ');
    
            if (properties['IsWiFiHotSpot']) {
                html.push('<img src="images/WiFiIcon.png" title="Wi-Fi Hotspot"/>');
            }
    
            if (properties['IsWheelchairAccessible']) {
                html.push('<img src="images/WheelChair-small.png" title="Wheelchair Accessible"/>');
            }
        }
    
        html.push('</div></div>');
    
        //Update the content and position of the pop-up window for the specified shape information.
        popup.setOptions({
    
            //Create a table from the properties in the feature.
            content:  html.join(''),
            position: shape.getCoordinates()
        });
    
        //Open the pop-up window.
        popup.open(map);
    }
    

Most már rendelkezik egy teljesen működőképes tárolókeresővel. Nyissa meg a index.html fájlt egy webböngészőben. Amikor a fürtök megjelennek a térképen, az alábbi módszerek bármelyikével kereshet egy helyet:

  1. A keresőmező.
  2. A Saját hely gomb kiválasztása
  3. Fürt kiválasztása
  4. Nagyítás a térképen az egyes helyek megtekintéséhez.

Amikor a felhasználó először választja ki a Saját hely gombot, a böngésző egy biztonsági figyelmeztetést jelenít meg, amely engedélyt kér a felhasználó tartózkodási helyének eléréséhez. Ha a felhasználó beleegyezik a tartózkodási hely megosztásába, a térkép nagyítja a felhasználó tartózkodási helyét, és megjelenik a közeli kávézók.

Képernyőkép a böngészőnek a felhasználó tartózkodási helyéhez való hozzáférésére vonatkozó kéréséről

Ha elég közelről nagyít egy olyan területre, ahol kávézók találhatók, a fürtök különálló helyekre különülnek el. Jelöljön ki egy ikont a térképen, vagy jelöljön ki egy elemet az oldalpanelen egy előugró ablak megjelenítéséhez. Az előugró ablak a kijelölt hely adatait jeleníti meg.

Képernyőkép a kész tárolókeresőről.

Ha a böngészőablakot 700 képpontnál kisebb méretűre méretezi át, vagy mobileszközön nyitja meg az alkalmazást, az elrendezés a kisebb képernyőkhöz jobban megfelel.

Képernyőkép az áruházkereső kis képernyős verziójáról

Ebben az oktatóanyagban megtanulta, hogyan hozhat létre alapszintű tárolókeresőt az Azure Térképek használatával. Az oktatóanyagban létrehozott tárolókereső minden szükséges funkcióval rendelkezhet. Hozzáadhat funkciókat az áruházkeresőhöz, vagy további előzetes funkciókat is használhat az egyéni felhasználói élmény érdekében:

  • Javaslatok engedélyezése a keresőmezőbe való beíráskor .
  • Több nyelv támogatásának hozzáadása.
  • Lehetővé teszi, hogy a felhasználó egy útvonal mentén szűrje a helyeket.
  • Adja hozzá a szűrők beállításának lehetőségét.
  • Adjon hozzá támogatást egy kezdeti keresési érték lekérdezési sztring használatával történő megadásához. Ha ezt a lehetőséget a tárolókeresőbe helyezi, a felhasználók könyvjelzővel jelölhetik meg és oszthatják meg a kereséseket. Emellett egy egyszerű módszert is kínál arra, hogy egy másik oldalról továbbítsa a keresést erre a lapra.
  • Helyezze üzembe az áruházkeresőt Azure-alkalmazás service webalkalmazásként.
  • Tárolja az adatokat egy adatbázisban, és keresse meg a közeli helyeket. További információkért tekintse meg az SQL Server térbeli adattípusainak áttekintését és a legközelebbi szomszéd térbeli adatainak lekérdezését.

További információk

  • A kész kódért tekintse meg a GitHubOn elérhető Simple Store Locator oktatóanyagot.
  • A minta élő megtekintéséhez tekintse meg a Simple Store Locatort az Azure Térképek Kódminták webhelyén.
  • További információ az Azure Térképek lefedettségéről és képességeiről a Nagyítási szintek és a csemperács használatával.
  • Az üzleti logikára adatvezérelt stíluskifejezéseket is használhat.

Következő lépések

További példakódok és az interaktív kódolási felület bemutatása: