Poznámka
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Tento kurz vás provede procesem vytvoření jednoduchého lokátoru úložiště pomocí Azure Maps.
V tomto kurzu se naučíte:
- Vytvořte novou webovou stránku pomocí rozhraní API pro mapové ovládací prvky Azure.
- Načtěte vlastní data ze souboru a zobrazte je na mapě.
- Pomocí Search Azure Maps vyhledejte adresu nebo zadejte dotaz.
- Získejte polohu uživatele z prohlížeče a zobrazte ho na mapě.
- Zkombinujte více vrstev a vytvořte na mapě vlastní symboly.
- Shluk datových bodů
- Přidejte do mapy ovládací prvky lupy.
Požadavky
- Pro účely tohoto kurzu se doporučuje Visual Studio Code , ale můžete použít libovolné vhodné integrované vývojové prostředí (IDE).
- Účet Azure Maps
- Klíč předplatného
Poznámka:
Další informace o ověřování ve službě Azure Maps najdete v tématu správa ověřování v Azure Maps.
Ukázkový kód
Tento kurz ukazuje, jak vytvořit lokátor obchodu pro fiktivní společnost Contoso Coffee spolu s tipy pro rozšíření lokátoru obchodu o další funkce.
Pokud se chcete podívat na živou ukázku toho, co vytváříte v tomto kurzu, podívejte se na web s ukázkami kódu služby Azure Maps na webu Simple Store Locator.
Pokud chcete lépe postupovat a zapojit se do tohoto kurzu, stáhněte si následující zdroje informací:
- Zdrojový kód aplikace Simple Store Locator.
- Data o umístění obchodu použitá k importu do datové sady pro vyhledávání obchodů.
- Mapové obrázky.
Funkce lokátoru obchodu
Tato část obsahuje seznam funkcí Azure Maps, které jsou ukázané v aplikaci lokátoru Contoso Coffee Store vytvořené v tomto kurzu.
Funkce uživatelského rozhraní
- Logo obchodu v záhlaví
- Mapa, která podporuje posouvání a přiblížení
- Tlačítko Moje umístění pro vyhledání aktuálního umístění uživatele
- Rozložení stránky, které se upravuje na základě šířky obrazovky zařízení
- Vyhledávací pole a tlačítko hledání
Funkční vlastnosti
- Událost
keypress
přidaná do vyhledávacího pole aktivuje hledání, když uživatel stiskne klávesu Enter. - Když se mapa přesune, vzdálenost k jednotlivým místům od středu mapy se přepočítá. Seznam výsledků se aktualizuje tak, aby zobrazil nejbližší umístění na vrcholu mapy.
- Když uživatel vybere výsledek v seznamu výsledků, mapa se zacentruje nad vybraným umístěním a informace o umístění se zobrazí v automaticky otevíraných otevíraných oknech.
- Když uživatel vybere konkrétní umístění, mapa aktivuje automaticky otevírané okno.
- Když se uživatel oddálí, umístění se seskupí do shluků. Každý shluk je reprezentován kruhem s číslem uvnitř kruhu. Clustery se formují a oddělují, protože uživatel změní úroveň přiblížení.
- Výběrem clusteru se mapa přiblíží o dvě úrovně a zaměří se na polohu clusteru.
Návrh vyhledávače obchodů
Následující snímek obrazovky ukazuje obecné rozložení aplikace lokátoru Contoso Coffee Store. Pokud chcete zobrazit živou ukázku a pracovat s ní, podívejte se na ukázkovou aplikaci Simple Store Locator na webu ukázek kódu Azure Maps.
Abychom maximalizovali užitečnost tohoto lokátoru obchodu, zahrneme responzivní rozložení, které se upraví, když je šířka obrazovky uživatele menší než 700 pixelů. Responzivní rozložení usnadňuje použití lokátoru obchodu na malé obrazovce, například na mobilním zařízení. Tady je snímek obrazovky zobrazující ukázku rozložení pro malé obrazovky:
Vytvořit datovou sadu umístění obchodu
Tato část popisuje, jak vytvořit datovou sadu úložišť, která chcete zobrazit na mapě. Datová sada pro lokátor Contoso Coffee se vytvoří v excelovém sešitu. Datová sada obsahuje 10 213 lokalit kávovaru Contoso Coffee, která se nacházejí v devíti zemích nebo oblastech: USA, Kanadě, Spojeném království, Francii, Německu, Itálii, Nizozemsku, Dánsku a Španělsku. Tady je snímek obrazovky s tím, jak data vypadají:
Stáhněte si excelový soubor obsahující úplnou datovou sadu ukázkové aplikace Contoso Coffee locator z datové složky úložiště ukázek kódu Azure Maps na GitHubu.
Na výše uvedeném snímku obrazovky s daty můžeme provést následující pozorování:
- Informace o poloze jsou uloženy v následujících šesti sloupcích: Adresa, Město, Obec (okres), Region (stát/provincie), PSČ (poštovní směrovací číslo) a Země.
- Sloupce Zeměpisná šířka a Zeměpisná délka obsahují souřadnice pro každé umístění contoso Coffee. Pokud nemáte souřadnicové informace, můžete pomocí Search určit souřadnice umístění.
- Některé další sloupce obsahují metadata, která souvisí s kávovary: telefonní číslo, logické sloupce a otevírání a zavírání obchodů ve 24hodinovém formátu. Logické sloupce jsou určené pro Wi-Fi a bezbariérový přístup. Můžete vytvořit vlastní sloupce, které obsahují metadata, která jsou pro vaše data o poloze relevantnější.
Poznámka:
Azure Maps vykresluje data v projekci Spherical Mercator EPSG:3857, ale čte data v EPSG:4326, která používají datovou základnu WGS84.
Načtení datové sady lokátoru kaváren Contoso
Datová sada lokátoru lokátoru Contoso Coffee shop je malá, takže ji můžete převést na textový soubor oddělený tabulátorem, který prohlížeč stáhne při načítání aplikace.
Tip
Pokud je vaše datová sada příliš velká pro stahování klienta nebo se často aktualizuje, můžete zvážit uložení datové sady do databáze. Po načtení dat do databáze můžete nastavit webovou službu, která přijímá dotazy na data, a pak výsledky odešle do prohlížeče uživatele.
Převod dat na textový soubor oddělený tabulátorem
Převod dat o poloze v obchodě Contoso Coffee shop z excelového sešitu na textový soubor oddělený tabulátorem:
Stáhněte si excelový sešit ContosoCoffee.xlsx a otevřete ho v Excelu.
Vyberte Soubor > uložit jako....
V rozevíracím seznamu Uložit jako typ vyberte Text (oddělený tabulátorem)(*.txt).
Pojmenujte soubor ContosoCoffee.
Pokud textový soubor otevřete v Poznámkovém bloku, bude vypadat podobně jako v následujícím textu:
Nastavení projektu
Otevřete Visual Studio Code nebo výběr vývojových prostředí.
Vyberte Soubor > otevřít pracovní prostor....
Vytvořte novou složku s názvem ContosoCoffee.
V průzkumníku vyberte ContosoCoffee .
Vytvořte následující tři soubory, které definují rozložení, styl a logiku pro aplikaci:
- index.html
- index.css
- index.js
Vytvořte složku s názvem data.
Do datové složky přidejte soubor ContosoCoffee.txt, který jste předtím vytvořili z excelového sešitu ContosoCoffee.xlsx.
Vytvořte další složku s názvem obrázky.
Pokud jste to ještě neudělali, stáhněte si 10 obrázků z adresáře obrázků v úložišti GitHub a přidejte je do složky obrázků .
Složka pracovního prostoru by teď měla vypadat jako na následujícím snímku obrazovky:
Vytvoření KÓDU HTML
Vytvoření kódu HTML:
Přidejte následující
meta
značky dohead
ze souboru 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">
Přidejte odkazy na soubory JavaScriptu a CSS webového ovládacího prvku Azure Maps:
<!-- 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>
Přidejte odkazy na index.js a 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>
Do textu dokumentu přidejte
header
značku. Do značkyheader
přidejte logo a název společnosti.<header> <img src="images/Logo.png" /> <span>Contoso Coffee</span> </header>
main
Přidejte značku a vytvořte vyhledávací panel s textovým polem a tlačítkem hledat. Můžete také přidatdiv
odkazy na mapu, seznam panelu a tlačítko Moje poloha GPS.<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>
Po dokončení by index.html měl v ukázkovém kódu kurzu vypadat jako Simple Store Locator.html.
Definování stylů CSS
Dalším krokem je definování stylů CSS. Styly CSS definují, jak jsou součásti aplikace rozloženy a jak vypadá aplikace.
Otevřete index.css.
Přidejte následující kód css:
Poznámka:
Styl
@media
definuje alternativní možnosti stylu, které se mají použít, když je šířka obrazovky menší než 700 pixelů.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); } }
Pokud aplikaci spustíte v tomto okamžiku, zobrazí se záhlaví, vyhledávací pole a tlačítko hledání. Mapa ale není viditelná, protože ještě nebyla načtena. Pokud se pokusíte provést hledání, nic se nestane. Další část popisuje přidání logiky JavaScriptu potřebné pro přístup ke všem funkcím lokátoru úložiště.
Přidání kódu JavaScript
Kód JavaScriptu v aplikaci lokátoru Contoso Coffee shop umožňuje následující procesy:
Přidá posluchač události, aby čekal, dokud stránka neukončí proces načítání. Po dokončení načítání stránky obslužná funkce události vytvoří další posluchače událostí, které budou monitorovat načítání mapy, a poskytovat funkce tlačítkům hledání a Moje poloha.
Když uživatel vybere tlačítko hledání nebo zadá do vyhledávacího pole umístění a pak stiskne enter, začne vyhledávání přibližných shod s dotazem uživatele. Kód předá pole hodnot ISO 2 země/oblasti do možnosti
countrySet
, aby omezil výsledky hledání na tyto země/oblasti. Omezení zemí nebo oblastí na vyhledávání pomáhá zvýšit přesnost vrácených výsledků.Po dokončení hledání se první výsledek umístění použije jako střed mapy. Když uživatel vybere tlačítko Moje místo, kód načte umístění uživatele pomocí rozhraní API geografické polohy HTML5, které je integrované v prohlížeči. Jakmile se poloha načte, kód zaměří mapu na polohu uživatele.
Přidání JavaScriptu:
Otevřete index.js.
Přidejte globální možnosti, které usnadňují aktualizaci nastavení. Definujte proměnné pro mapu, automaticky otevírané okno, zdroj dat, vrstvu ikon a značku HTML. Nastavte značku HTML tak, aby označí střed vyhledávací oblasti. Definujte instanci klienta služby Azure Maps Search.
//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>';
Přidejte následující inicializační kód. Nezapomeňte nahradit
<Your Azure Maps Key>
klíčem předplatného Azure Maps.Tip
Při použití automaticky otevíraných oken je nejlepší vytvořit jednu
Popup
instanci a znovu ji znovu použít aktualizací jejího obsahu a pozice. Pro každouPopup
instanci, kterou přidáte do kódu, se na stránku přidá několik prvků DOM. Čím více prvků DOM je na stránce, tím více toho musí prohlížeč sledovat. Pokud existuje příliš mnoho položek, může se prohlížeč zpomalit.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;
V obslužné rutině události mapy
ready
přidejte ovládací prvek přiblížení a HTML ukazatel, aby se zobrazil střed vyhledávací oblasti.//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);
Do obslužné rutiny
ready
události mapy přidejte zdroj dat. Potom proveďte volání pro načtení a parsování datové sady. Umožněte clustering u datového zdroje. Shlukování na zdroji dat seskupuje překrývající se body dohromady v jednom klastru. Když se uživatel přibližuje, clustery se oddělují do jednotlivých bodů. Toto chování poskytuje lepší uživatelské prostředí a zlepšuje výkon.//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();
Po načtení datové sady do obslužné funkce události mapy
ready
definujte sadu vrstev pro vykreslení dat. Bublinová vrstva vykresluje skupinové datové body. Vrstva symbolů vykreslí počet bodů v každém clusteru nad vrstvou bubliny. Druhá vrstva symbolů vykreslí vlastní ikonu pro jednotlivá umístění na mapě.Přidejte události
mouseover
amouseout
do vrstev bublin a ikon, aby se změnil kurzor myši, když uživatel najede myší na shluk nebo ikonu na mapě.click
Přidejte událost do vrstvy bublin clusteru. Tatoclick
událost přiblíží mapu o dvě úrovně a vycentruje mapu na cluster, když uživatel vybere jakýkoli cluster.click
Přidejte událost do vrstvy ikon. Tatoclick
událost zobrazí automaticky otevírané okno s podrobnostmi o kavárně, když uživatel vybere ikonu místa. Přidejte do mapy událost pro monitorování, kdy se mapa dokončí pohybovat. Když se tato událost aktivuje, aktualizujte položky na panelu seznamu.//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(); }); });
Pokud je potřeba datová sada v kavárně, musí se nejdřív stáhnout. Po stažení musí být soubor rozdělený na řádky. První řádek obsahuje informace o záhlaví. Abychom usnadnili sledování kódu, parsujeme hlavičku do objektu, který pak můžeme použít k vyhledání indexu buňky pro každou vlastnost. Po prvním řádku projděte zbývající řádky a vytvořte bodový prvek. Přidejte funkci bodu do zdroje dat. Nakonec aktualizujte panel seznamu.
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(); }); }
Po aktualizaci panelu seznamu se vypočítá vzdálenost. Tato vzdálenost je od středu mapy až k všem bodovým prvkům ve stávajícím zobrazení mapy. Funkce se pak seřadí podle vzdálenosti. HTML je vygenerován k zobrazení jednotlivých lokalit na panelu seznamu.
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(''); }
Když uživatel vybere položku na panelu seznamu, obrazec, ke kterému položka souvisí, se načte ze zdroje dat. Vyskakovací okno je vytvořeno na základě informací o vlastnostech uložených v obrazci. Mapa se zacentruje nad obrazcem. Pokud je mapa menší než 700 pixelů široká, je zobrazení mapy posunuté, aby se zobrazilo automaticky otevírané okno.
//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); }
Teď máte plně funkční vyhledávač obchodů. Otevřete soubor index.html ve webovém prohlížeči. Když se clustery zobrazí na mapě, můžete vyhledat umístění pomocí některé z následujících metod:
- Vyhledávací pole.
- Výběr tlačítka Moje umístění
- Výběr clusteru
- Přiblížením na mapě zobrazíte jednotlivá umístění.
Když uživatel poprvé vybere tlačítko Moje místo, zobrazí se v prohlížeči upozornění zabezpečení, které požádá o oprávnění pro přístup k umístění uživatele. Pokud uživatel souhlasí se sdílením své polohy, mapa se přiblíží na místě uživatele a zobrazí se blízké kavárny.
Když přiblížíte dostatečně blízko v oblasti, kde jsou umístění kaváren, shluky se rozdělují na jednotlivé lokace. Výběrem jedné z ikon na mapě nebo výběrem položky na bočním panelu zobrazíte automaticky otevírané okno. Automaticky otevírané okno zobrazí informace o vybraném umístění.
Pokud změníte velikost okna prohlížeče na méně než 700 pixelů na šířku nebo otevřete aplikaci na mobilním zařízení, změní se rozložení, které bude vhodnější pro menší obrazovky.
V tomto kurzu jste se naučili vytvořit základní lokátor obchodu pomocí Azure Maps. Lokátor obchodu, který vytvoříte v tomto kurzu, může mít všechny funkce, které potřebujete. Do lokátoru obchodu můžete přidat funkce nebo použít pokročilejší funkce pro vlastní uživatelské prostředí:
- Povolit návrhy při psaní ve vyhledávacím poli.
- Přidání podpory pro více jazyků
- Umožňuje uživateli filtrovat umístění podél trasy.
- Přidejte možnost nastavit filtry.
- Přidejte podporu pro zadání počáteční hodnoty hledání pomocí řetězce dotazu. Když tuto možnost zahrnete do lokátoru obchodu, uživatelé pak budou moct vytvářet záložky a sdílet hledání. Poskytuje také snadnou metodu pro předávání hledání na tuto stránku z jiné stránky.
- Nasaďte lokátor obchodu jako webovou aplikaci služby Azure App Service.
- Uložte data do databáze a vyhledejte nejbližší umístění. Další informace najdete v přehledu prostorových datových typů SQL Serveru a dotazování prostorových dat pro nejbližšího souseda.
Další informace
- Dokončený kód najdete v kurzu lokátoru Simple Store na GitHubu.
- Chcete-li tuto ukázku zobrazit živě, podívejte se na jednoduchý lokátor obchodů na webu ukázek kódu Azure Maps.
- Zjistěte více o pokrytí a funkčnosti Azure Maps pomocí úrovní přiblížení a dlaždicové mřížky.
- Můžete také použít výrazy stylu řízené daty pro obchodní logiku.
Další kroky
Další příklady kódu a prostředí pro interaktivní psaní kódu: