Tworzenie źródła danych (android SDK)

Zestaw Azure Mapy Android SDK przechowuje dane w źródłach danych. Korzystanie ze źródeł danych optymalizuje operacje na danych na potrzeby wykonywania zapytań i renderowania. Obecnie istnieją dwa typy źródeł danych:

  • Źródło GeoJSON: zarządza nieprzetworzonymi danymi lokalizacji w formacie GeoJSON lokalnie. Dobre dla małych i średnich zestawów danych (w górę setki tysięcy kształtów).
  • Źródło kafelka wektorowego: ładuje dane sformatowane jako kafelki wektorowe dla bieżącego widoku mapy na podstawie systemu układania map. Idealne rozwiązanie dla dużych i ogromnych zestawów danych (miliony lub miliardy kształtów).

Uwaga

Wycofanie zestawu AZURE Mapy Android SDK

Zestaw Azure Mapy Native SDK dla systemu Android jest teraz przestarzały i zostanie wycofany w dniu 3.31.25. Aby uniknąć przerw w działaniu usługi, przeprowadź migrację do zestawu Sdk sieci Web usługi Azure Mapy do 31/31/25. Aby uzyskać więcej informacji, zobacz Przewodnik migracji zestawu SDK platformy Azure Mapy Android.

Źródło danych GeoJSON

Usługa Azure Mapy używa formatu GeoJSON jako jednego z podstawowych modeli danych. GeoJSON to otwarty standardowy sposób geoprzestrzennego reprezentowania danych geoprzestrzennych w formacie JSON. Klasy GeoJSON dostępne w zestawie AZURE Mapy Android SDK do łatwego tworzenia i serializowania danych GeoJSON. Załaduj i zapisz dane GeoJSON w klasie i renderuj DataSource je przy użyciu warstw. Poniższy kod pokazuje, jak można tworzyć obiekty GeoJSON w usłudze Azure Mapy.

/*
    Raw GeoJSON feature

    {
         "type": "Feature",
         "geometry": {
             "type": "Point",
             "coordinates": [-100, 45]
         },
         "properties": {
             "custom-property": "value"
         }
    }

*/

//Create a point feature.
Feature feature = Feature.fromGeometry(Point.fromLngLat(-100, 45));

//Add a property to the feature.
feature.addStringProperty("custom-property", "value");

//Add the feature to the data source.
source.add(feature);
/*
    Raw GeoJSON feature

    {
         "type": "Feature",
         "geometry": {
             "type": "Point",
             "coordinates": [-100, 45]
         },
         "properties": {
             "custom-property": "value"
         }
    }

*/

//Create a point feature.
val feature = Feature.fromGeometry(Point.fromLngLat(-100, 45))

//Add a property to the feature.
feature.addStringProperty("custom-property", "value")

//Add the feature to the data source.
source.add(feature)

Napiwek

Dane GeoJSON można dodać do DataSource wystąpienia przy użyciu jednej z trzech metod: add, importDataFromUrli setShapes. Metoda setShapes zapewnia wydajny sposób zastępowania wszystkich danych w źródle danych. Jeśli wywołasz clear metody , aby add zastąpić wszystkie dane w źródle danych, do mapy zostaną wykonane dwa wywołania renderowania. Metoda setShape czyści i dodaje dane do źródła danych za pomocą pojedynczego wywołania renderowania do mapy.

Alternatywnie właściwości można załadować do obiektu JsonObject, a następnie przekazać je do funkcji podczas jej tworzenia, jak pokazano w poniższym przykładowym kodzie.

//Create a JsonObject to store properties for the feature.
JsonObject properties = new JsonObject();
properties.addProperty("custom-property", "value");

Feature feature = Feature.fromGeometry(Point.fromLngLat(-100, 45), properties);
//Create a JsonObject to store properties for the feature.
val properties = JsonObject()
properties.addProperty("custom-property", "value")

val feature = Feature.fromGeometry(Point.fromLngLat(-100, 45), properties)

Po utworzeniu funkcji GeoJSON można dodać źródło danych do mapy za pomocą sources właściwości mapy. Poniższy kod pokazuje, jak utworzyć obiekt DataSource, dodać go do mapy i dodać funkcję do źródła danych.

//Create a data source and add it to the map.
DataSource source = new DataSource();
map.sources.add(source);

//Add GeoJSON feature to the data source.
source.add(feature);

Poniższy kod przedstawia kilka sposobów tworzenia funkcji GeoJSON, FeatureCollection i geometrii.

//GeoJSON Point Geometry
Point point = Point.fromLngLat(LONGITUDE, LATITUDE);

//GeoJSON Point Geometry
LineString linestring = LineString.fromLngLats(PointList);

//GeoJSON Polygon Geometry
Polygon polygon = Polygon.fromLngLats(listOfPointList);

Polygon polygonFromOuterInner = Polygon.fromOuterInner(outerLineStringObject,innerLineStringObject);

//GeoJSON MultiPoint Geometry
MultiPoint multiPoint = MultiPoint.fromLngLats(PointList);

//GeoJSON MultiLineString Geometry
MultiLineString multiLineStringFromLngLat = MultiLineString.fromLngLats(listOfPointList);

MultiLineString multiLineString = MultiLineString.fromLineString(singleLineString);

//GeoJSON MultiPolygon Geometry
MultiPolygon multiPolygon = MultiPolygon.fromLngLats(listOflistOfPointList);

MultiPolygon multiPolygonFromPolygon = MultiPolygon.fromPolygon(polygon);

MultiPolygon multiPolygonFromPolygons = MultiPolygon.fromPolygons(PolygonList);

//GeoJSON Feature
Feature pointFeature = Feature.fromGeometry(Point.fromLngLat(LONGITUDE, LATITUDE));

//GeoJSON FeatureCollection 
FeatureCollection featureCollectionFromSingleFeature = FeatureCollection.fromFeature(pointFeature);

FeatureCollection featureCollection = FeatureCollection.fromFeatures(listOfFeatures);
//GeoJSON Point Geometry
val point = Point.fromLngLat(LONGITUDE, LATITUDE)

//GeoJSON Point Geometry
val linestring = LineString.fromLngLats(PointList)

//GeoJSON Polygon Geometry
val polygon = Polygon.fromLngLats(listOfPointList)

val polygonFromOuterInner = Polygon.fromOuterInner(outerLineStringObject, innerLineStringObject)

//GeoJSON MultiPoint Geometry
val multiPoint = MultiPoint.fromLngLats(PointList)

//GeoJSON MultiLineString Geometry
val multiLineStringFromLngLat = MultiLineString.fromLngLats(listOfPointList)

val multiLineString = MultiLineString.fromLineString(singleLineString)

//GeoJSON MultiPolygon Geometry
val multiPolygon = MultiPolygon.fromLngLats(listOflistOfPointList)

val multiPolygonFromPolygon = MultiPolygon.fromPolygon(polygon)

val multiPolygonFromPolygons = MultiPolygon.fromPolygons(PolygonList)

//GeoJSON Feature
val pointFeature = Feature.fromGeometry(Point.fromLngLat(LONGITUDE, LATITUDE))

//GeoJSON FeatureCollection 
val featureCollectionFromSingleFeature = FeatureCollection.fromFeature(pointFeature)

val featureCollection = FeatureCollection.fromFeatures(listOfFeatures)

Serializowanie i deserializowanie danych GeoJSON

Wszystkie klasy kolekcji funkcji, funkcji i geometrii mają fromJson() i toJson() statyczne metody, które ułatwiają serializacji. Sformatowany prawidłowy ciąg JSON przekazany przez fromJson() metodę tworzy obiekt geometryczny. Ta fromJson() metoda oznacza również, że można użyć formatu Gson lub innych strategii serializacji/deserializacji. Poniższy kod pokazuje, jak pobrać funkcję GeoJSON ze skreśloną ciągiem i deserializować ją w klasie Feature, a następnie serializować ją z powrotem do ciągu GeoJSON.

//Take a stringified GeoJSON object.
String GeoJSON_STRING = "{"
    + "      \"type\": \"Feature\","            
    + "      \"geometry\": {"
    + "            \"type\": \"Point\""
    + "            \"coordinates\": [-100, 45]"
    + "      },"
    + "      \"properties\": {"
    + "            \"custom-property\": \"value\""
    + "      },"
    + "}";

//Deserialize the JSON string into a feature.
Feature feature = Feature.fromJson(GeoJSON_STRING);

//Serialize a feature collection to a string.
String featureString = feature.toJson();
//Take a stringified GeoJSON object.
val GeoJSON_STRING = ("{"
        + "      \"type\": \"Feature\","
        + "      \"geometry\": {"
        + "            \"type\": \"Point\""
        + "            \"coordinates\": [-100, 45]"
        + "      },"
        + "      \"properties\": {"
        + "            \"custom-property\": \"value\""
        + "      },"
        + "}")

//Deserialize the JSON string into a feature.
val feature = Feature.fromJson(GeoJSON_STRING)

//Serialize a feature collection to a string.
val featureString = feature.toJson()

Importowanie danych GeoJSON z folderu internetowego lub zawartości

Większość plików GeoJSON zawiera funkcję FeatureCollection. Odczytaj pliki GeoJSON jako ciągi i użyto FeatureCollection.fromJson metody do deserializacji.

Klasa DataSource ma wbudowaną metodę o nazwie importDataFromUrl , która może ładować pliki GeoJSON przy użyciu adresu URL do pliku w Internecie lub w folderze zasobów. Ta metoda musi zostać wywołana przed dodaniu źródła danych do mapy.

zone_pivot_groups: azure-maps-android

//Create a data source and add it to the map.
DataSource source = new DataSource();

//Import the geojson data and add it to the data source.
source.importDataFromUrl("URL_or_FilePath_to_GeoJSON_data");

//Examples:
//source.importDataFromUrl("asset://sample_file.json");
//source.importDataFromUrl("https://example.com/sample_file.json");

//Add data source to the map.
map.sources.add(source);
//Create a data source and add it to the map.
var source = new DataSource()

//Import the geojson data and add it to the data source.
source.importDataFromUrl("URL_or_FilePath_to_GeoJSON_data")

//Examples:
//source.importDataFromUrl("asset://sample_file.json")
//source.importDataFromUrl("https://example.com/sample_file.json")

//Add data source to the map.
map.sources.add(source)

Metoda importDataFromUrl zapewnia łatwy sposób ładowania źródła danych GeoJSON do źródła danych, ale zapewnia ograniczoną kontrolę nad tym, jak dane są ładowane i co się stanie po załadowaniu. Poniższy kod to klasa wielokrotnego użytku do importowania danych z folderu sieci Web lub zasobów i zwracania ich do wątku interfejsu użytkownika za pośrednictwem funkcji wywołania zwrotnego. Następnie dodaj więcej logiki ładowania po załadowaniu w wywołaniu zwrotnym, aby przetworzyć dane, dodać je do mapy, obliczyć pole ograniczenia i zaktualizować aparat map.

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.webkit.URLUtil;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.net.ssl.HttpsURLConnection;

public class Utils {

    interface SimpleCallback {
        void notify(String result);
    }

    /**
     * Imports data from a web url or asset file name and returns it to a callback.
     * @param urlOrFileName A web url or asset file name that points to data to load.
     * @param context The context of the app.
     * @param callback The callback function to return the data to.
     */
    public static void importData(String urlOrFileName, Context context, SimpleCallback callback){
        importData(urlOrFileName, context, callback, null);
    }

    /**
     * Imports data from a web url or asset file name and returns it to a callback.
     * @param urlOrFileName A web url or asset file name that points to data to load.
     * @param context The context of the app.
     * @param callback The callback function to return the data to.
     * @param error A callback function to return errors to.
     */
    public static void importData(String urlOrFileName, Context context, SimpleCallback callback, SimpleCallback error){
        if(urlOrFileName != null && callback != null) {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            Handler handler = new Handler(Looper.getMainLooper());

            executor.execute(() -> {
                String data = null;

                try {

                    if(URLUtil.isNetworkUrl(urlOrFileName)){
                        data = importFromWeb(urlOrFileName);
                    } else {
                        //Assume file is in assets folder.
                        data = importFromAssets(context, urlOrFileName);
                    }

                    final String result = data;

                    handler.post(() -> {
                        //Ensure the resulting data string is not null or empty.
                        if (result != null && !result.isEmpty()) {
                            callback.notify(result);
                        } else {
                            error.notify("No data imported.");
                        }
                    });
                } catch(Exception e) {
                    if(error != null){
                        error.notify(e.getMessage());
                    }
                }
            });
        }
    }

    /**
     * Imports data from an assets file as a string.
     * @param context The context of the app.
     * @param fileName The asset file name.
     * @return
     * @throws IOException
     */
    private static String importFromAssets(Context context, String fileName) throws IOException {
        InputStream stream = null;

        try {
            stream = context.getAssets().open(fileName);

            if(stream != null) {
                return readStreamAsString(stream);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // Close Stream and disconnect HTTPS connection.
            if (stream != null) {
                stream.close();
            }
        }

        return null;
    }

    /**
     * Imports data from the web as a string.
     * @param url URL to the data.
     * @return
     * @throws IOException
     */
    private static String importFromWeb(String url) throws IOException {
        InputStream stream = null;
        HttpsURLConnection connection = null;
        String result = null;

        try {
            connection = (HttpsURLConnection) new URL(url).openConnection();

            //For this use case, set HTTP method to GET.
            connection.setRequestMethod("GET");

            //Open communications link (network traffic occurs here).
            connection.connect();

            int responseCode = connection.getResponseCode();
            if (responseCode != HttpsURLConnection.HTTP_OK) {
                throw new IOException("HTTP error code: " + responseCode);
            }

            //Retrieve the response body as an InputStream.
            stream = connection.getInputStream();

            if (stream != null) {
                return readStreamAsString(stream);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // Close Stream and disconnect HTTPS connection.
            if (stream != null) {
                stream.close();
            }
            if (connection != null) {
                connection.disconnect();
            }
        }

        return result;
    }

    /**
     * Reads an input stream as a string.
     * @param stream Stream to convert.
     * @return
     * @throws IOException
     */
    private static String readStreamAsString(InputStream stream) throws IOException {
        //Convert the contents of an InputStream to a String.
        BufferedReader in = new BufferedReader(new InputStreamReader(stream, "UTF-8"));

        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }

        in.close();

        return response.toString();
    }
}
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.webkit.URLUtil
import java.net.URL
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

class Utils {
    companion object {

        /**
            * Imports data from a web url or asset file name and returns it to a callback.
            * @param urlOrFileName A web url or asset file name that points to data to load.
            * @param context The context of the app.
            * @param callback The callback function to return the data to.
            */
        fun importData(urlOrFileName: String?, context: Context, callback: (String?) -> Unit) {
            importData(urlOrFileName, context, callback, null)
        }

        /**
            * Imports data from a web url or asset file name and returns it to a callback.
            * @param urlOrFileName A web url or asset file name that points to data to load.
            * @param context The context of the app.
            * @param callback The callback function to return the data to.
            * @param error A callback function to return errors to.
            */
        public fun importData(urlOrFileName: String?, context: Context, callback: (String?) -> Unit, error: ((String?) -> Unit)?) {
            if (urlOrFileName != null && callback != null) {
                val executor: ExecutorService = Executors.newSingleThreadExecutor()
                val handler = Handler(Looper.getMainLooper())
                executor.execute {
                    var data: String? = null

                    try {
                        data = if (URLUtil.isNetworkUrl(urlOrFileName)) {
                            URL(urlOrFileName).readText()
                        } else { //Assume file is in assets folder.
                            context.assets.open(urlOrFileName).bufferedReader().use{
                                it.readText()
                            }
                        }

                        handler.post {
                            //Ensure the resulting data string is not null or empty.
                            if (data != null && !data.isEmpty()) {
                                callback(data)
                            } else {
                                error!!("No data imported.")
                            }
                        }
                    } catch (e: Exception) {
                        error!!(e.message)
                    }
                }
            }
        }
    }
}

Poniższy kod pokazuje, jak używać tego narzędzia do importowania danych GeoJSON jako ciągu i zwracania ich do wątku interfejsu użytkownika za pośrednictwem wywołania zwrotnego. W wywołaniu zwrotnym dane ciągu można serializować w kolekcji funkcji GeoJSON i dodawane do źródła danych. Opcjonalnie zaktualizuj aparat map, aby skoncentrować się na danych.

//Create a data source and add it to the map.
DataSource source = new DataSource();
map.sources.add(source);

//Import the geojson data and add it to the data source.
Utils.importData("URL_or_FilePath_to_GeoJSON_data",
    this,
    (String result) -> {
        //Parse the data as a GeoJSON Feature Collection.
        FeatureCollection fc = FeatureCollection.fromJson(result);

        //Add the feature collection to the data source.
        source.add(fc);

        //Optionally, update the maps camera to focus in on the data.

        //Calculate the bounding box of all the data in the Feature Collection.
        BoundingBox bbox = MapMath.fromData(fc);

        //Update the maps camera so it is focused on the data.
        map.setCamera(
            bounds(bbox),
            padding(20));
    });
//Create a data source and add it to the map.
DataSource source = new DataSource();
map.sources.add(source);

//Import the GeoJSON data and add it to the data source.
Utils.importData("SamplePoiDataSet.json", this) { 
    result: String? ->
        //Parse the data as a GeoJSON Feature Collection.
            val fc = FeatureCollection.fromJson(result!!)

        //Add the feature collection to the data source.
        source.add(fc)

        //Optionally, update the maps camera to focus in on the data.

        //Calculate the bounding box of all the data in the Feature Collection.
        val bbox = MapMath.fromData(fc);

        //Update the maps camera so it is focused on the data.
        map.setCamera(
            bounds(bbox),

            //Padding added to account for pixel size of rendered points.
            padding(20)
        )
    }

Aktualizowanie funkcji

Klasa DataSource ułatwia dodawanie i usuwanie funkcji. Zaktualizowanie geometrii lub właściwości funkcji wymaga zastąpienia funkcji w źródle danych. Istnieją dwie metody, które mogą służyć do aktualizowania funkcji:

  1. Utwórz nowe funkcje z żądanymi aktualizacjami i zastąp wszystkie funkcje w źródle danych przy użyciu setShapes metody . Ta metoda sprawdza się dobrze, gdy chcesz zaktualizować wszystkie funkcje w źródle danych.
DataSource source;

private void onReady(AzureMap map) {
    //Create a data source and add it to the map.
    source = new DataSource();
    map.sources.add(source);

    //Create a feature and add it to the data source.
    Feature myFeature = Feature.fromGeometry(Point.fromLngLat(0,0));
    myFeature.addStringProperty("Name", "Original value");

    source.add(myFeature);
}

private void updateFeature(){
    //Create a new replacement feature with an updated geometry and property value.
    Feature myNewFeature = Feature.fromGeometry(Point.fromLngLat(-10, 10));
    myNewFeature.addStringProperty("Name", "New value");

    //Replace all features to the data source with the new one.
    source.setShapes(myNewFeature);
}
var source: DataSource? = null

private fun onReady(map: AzureMap) {
    //Create a data source and add it to the map.
    source = DataSource()
    map.sources.add(source)

    //Create a feature and add it to the data source.
    val myFeature = Feature.fromGeometry(Point.fromLngLat(0.0, 0.0))
    myFeature.addStringProperty("Name", "Original value")
    source!!.add(myFeature)
}

private fun updateFeature() {
    //Create a new replacement feature with an updated geometry and property value.
    val myNewFeature = Feature.fromGeometry(Point.fromLngLat(-10.0, 10.0))
    myNewFeature.addStringProperty("Name", "New value")

    //Replace all features to the data source with the new one.
    source!!.setShapes(myNewFeature)
}
  1. Śledź wystąpienie funkcji w zmiennej i przekaż je do metody źródeł remove danych, aby je usunąć. Utwórz nowe funkcje z żądanymi aktualizacjami, zaktualizuj odwołanie do zmiennej i dodaj ją do źródła danych przy użyciu add metody .
DataSource source;
Feature myFeature;

private void onReady(AzureMap map) {
    //Create a data source and add it to the map.
    source = new DataSource();
    map.sources.add(source);

    //Create a feature and add it to the data source.
    myFeature = Feature.fromGeometry(Point.fromLngLat(0,0));
    myFeature.addStringProperty("Name", "Original value");

    source.add(myFeature);
}

private void updateFeature(){
    //Remove the feature instance from the data source.
    source.remove(myFeature);

    //Get properties from original feature.
    JsonObject props = myFeature.properties();

    //Update a property.
    props.addProperty("Name", "New value");

    //Create a new replacement feature with an updated geometry.
    myFeature = Feature.fromGeometry(Point.fromLngLat(-10, 10), props);

    //Re-add the feature to the data source.
    source.add(myFeature);
}
var source: DataSource? = null
var myFeature: Feature? = null

private fun onReady(map: AzureMap) {
    //Create a data source and add it to the map.
    source = DataSource()
    map.sources.add(source)

    //Create a feature and add it to the data source.
    myFeature = Feature.fromGeometry(Point.fromLngLat(0.0, 0.0))
    myFeature.addStringProperty("Name", "Original value")
    source!!.add(myFeature)
}

private fun updateFeature() {
    //Remove the feature instance from the data source.
    source!!.remove(myFeature)

    //Get properties from original feature.
    val props = myFeature!!.properties()

    //Update a property.
    props!!.addProperty("Name", "New value")

    //Create a new replacement feature with an updated geometry.
    myFeature = Feature.fromGeometry(Point.fromLngLat(-10.0, 10.0), props)

    //Re-add the feature to the data source.
    source!!.add(myFeature)
}

Napiwek

Jeśli masz pewne dane, które będą regularnie aktualizowane, a inne dane, które będą rzadko zmieniane, najlepiej podzielić je na oddzielne wystąpienia źródła danych. Gdy aktualizacja występuje w źródle danych, wymusza na mapie przemalowania wszystkich funkcji w źródle danych. Dzięki podzieleniu tych danych tylko funkcje, które są regularnie aktualizowane, zostaną przemalowane po wystąpieniu aktualizacji w tym jednym źródle danych, podczas gdy funkcje w drugim źródle danych nie będą musiały zostać przemalowane. Pomaga to w wydajności.

Źródło kafelka wektorowego

Źródło kafelka wektorowego opisuje sposób uzyskiwania dostępu do warstwy kafelka wektorowego. VectorTileSource Użyj klasy , aby utworzyć wystąpienie źródła kafelka wektorowego. Warstwy kafelków wektorowych są podobne do warstw kafelków, ale nie są takie same. Warstwa kafelka to obraz rastrowy. Warstwy kafelków wektorowych są skompresowanym plikiem w formacie PBF . Ten skompresowany plik zawiera dane mapy wektorów i co najmniej jedną warstwę. Plik można renderować i stylizowany na kliencie na podstawie stylu każdej warstwy. Dane na kafelku wektorowym zawierają cechy geograficzne w postaci punktów, linii i wielokątów. Istnieje kilka zalet używania warstw kafelków wektorowych zamiast warstw kafelków rastrowych:

  • Rozmiar pliku kafelka wektorowego jest zwykle znacznie mniejszy niż równoważny kafelek rastrowy. W związku z tym używana jest mniejsza przepustowość. Oznacza to mniejsze opóźnienie, szybszą mapę i lepsze środowisko użytkownika.
  • Ponieważ kafelki wektorowe są renderowane na kliencie, dostosowują się do rozdzielczości wyświetlanego urządzenia. W związku z tym renderowane mapy są bardziej dobrze zdefiniowane z krystalicznie przejrzystymi etykietami.
  • Zmiana stylu danych w mapach wektorowych nie wymaga ponownego pobrania danych, ponieważ nowy styl można zastosować na kliencie. Z kolei zmiana stylu warstwy kafelka rastrowego zwykle wymaga ładowania kafelków z serwera, a następnie zastosowania nowego stylu.
  • Ponieważ dane są dostarczane w postaci wektorowej, przetwarzanie po stronie serwera jest mniej wymagane do przygotowania danych. W związku z tym nowsze dane mogą być udostępniane szybciej.

Usługa Azure Mapy jest zgodna ze specyfikacją kafelka Mapbox Vector— otwartym standardem. Usługa Azure Mapy udostępnia następujące usługi kafelków wektorowych w ramach platformy:

Napiwek

W przypadku korzystania z kafelków obrazów wektorowych lub rastrowych z usługi renderowania usługi Azure Mapy za pomocą zestawu WEB SDK możesz zastąpić atlas.microsoft.com symbol zastępczy azmapsdomain.invalid. Ten symbol zastępczy zostanie zastąpiony tą samą domeną używaną przez mapę i automatycznie dołączy te same szczegóły uwierzytelniania. Znacznie upraszcza to uwierzytelnianie za pomocą usługi renderowania podczas korzystania z uwierzytelniania firmy Microsoft Entra.

Aby wyświetlić dane ze źródła kafelka wektorowego na mapie, połącz źródło z jedną z warstw renderowania danych. Wszystkie warstwy używające źródła wektorów muszą określać sourceLayer wartość w opcjach. Poniższy kod ładuje usługę kafelek wektora przepływu ruchu platformy Azure Mapy jako źródło kafelka wektora, a następnie wyświetla go na mapie przy użyciu warstwy liniowej. To wektorowe źródło kafelków ma jeden zestaw danych w warstwie źródłowej o nazwie "Przepływ ruchu". Dane wiersza w tym zestawie danych mają właściwość o nazwie traffic_level , która jest używana w tym kodzie do wybierania koloru i skalowania rozmiaru linii.

//Formatted URL to the traffic flow vector tiles, with the maps subscription key appended to it.
String trafficFlowUrl = "https://azmapsdomain.invalid/traffic/flow/tile/pbf?api-version=1.0&style=relative&zoom={z}&x={x}&y={y}";

//Create a vector tile source and add it to the map.
VectorTileSource source = new VectorTileSource(
    tiles(new String[] { trafficFlowUrl }),
    maxSourceZoom(22)
);
map.sources.add(source);

//Create a layer for traffic flow lines.
LineLayer layer = new LineLayer(source,
    //The name of the data layer within the data source to pass into this rendering layer.
    sourceLayer("Traffic flow"),

    //Color the roads based on the traffic_level property.
    strokeColor(
        interpolate(
            linear(),
            get("traffic_level"),
            stop(0, color(Color.RED)),
            stop(0.33, color(Color.YELLOW)),
            stop(0.66, color(Color.GREEN))
        )
    ),

    //Scale the width of roads based on the traffic_level property.
    strokeWidth(
        interpolate(
            linear(),
            get("traffic_level"),
            stop(0, 6),
            stop(1,1)
        )
    )
);

//Add the traffic flow layer below the labels to make the map clearer.
map.layers.add(layer, "labels");
//Formatted URL to the traffic flow vector tiles, with the maps subscription key appended to it.
val trafficFlowUrl = "https://azmapsdomain.invalid/traffic/flow/tile/pbf?api-version=1.0&style=relative&zoom={z}&x={x}&y={y}"

//Create a vector tile source and add it to the map.
val source = VectorTileSource(
    tiles(arrayOf(trafficFlowUrl)),
    maxSourceZoom(22)
)
map.sources.add(source)

//Create a layer for traffic flow lines.
val layer = LineLayer(
    source,  //The name of the data layer within the data source to pass into this rendering layer.
    sourceLayer("Traffic flow"),  //Color the roads based on the traffic_level property.
    strokeColor(
        interpolate(
            linear(),
            get("traffic_level"),
            stop(0, color(Color.RED)),
            stop(0.33, color(Color.YELLOW)),
            stop(0.66, color(Color.GREEN))
        )
    ),  //Scale the width of roads based on the traffic_level property.
    strokeWidth(
        interpolate(
            linear(),
            get("traffic_level"),
            stop(0, 6),
            stop(1, 1)
        )
    )
)

//Add the traffic flow layer below the labels to make the map clearer.
map.layers.add(layer, "labels")

Mapa z kolorowymi liniami dróg z poziomami przepływu ruchu

Połączenie źródła danych do warstwy

Dane są renderowane na mapie przy użyciu warstw renderowania. Co najmniej jedna warstwa renderowania może odwoływać się do jednego źródła danych. Następujące warstwy renderowania wymagają źródła danych:

  • Warstwa bąbelkowa — renderuje dane punktów jako skalowane okręgi na mapie.
  • Warstwa symboli — renderuje dane punktów jako ikony lub tekst.
  • Warstwa mapy cieplnej — renderuje dane punktów jako mapę cieplną o gęstości.
  • Warstwa liniowa — renderuje linię i renderuje kontur wielokątów.
  • Warstwa wielokątna — wypełnia obszar wielokąta kolorem stałym lub wzorcem obrazu.

Poniższy kod pokazuje, jak utworzyć źródło danych, dodać je do mapy i połączyć go z warstwą bąbelka. Następnie zaimportuj dane punktu GeoJSON ze zdalnej lokalizacji do źródła danych.

//Create a data source and add it to the map.
DataSource source = new DataSource();

//Import the geojson data and add it to the data source.
source.importDataFromUrl("URL_or_FilePath_to_GeoJSON_data");

//Add data source to the map.
map.sources.add(source);

//Create a layer that defines how to render points in the data source and add it to the map.
BubbleLayer layer = new BubbleLayer(source);
map.layers.add(layer);
//Create a data source and add it to the map.
val source = DataSource()

//Import the geojson data and add it to the data source.
source.importDataFromUrl("URL_or_FilePath_to_GeoJSON_data")

//Add data source to the map.
map.sources.add(source)

Istnieje więcej warstw renderowania, które nie łączą się z tymi źródłami danych, ale bezpośrednio ładują dane do renderowania.

  • Warstwa kafelka — nakłada warstwę kafelka rastrowego na wierzchu mapy.

Jedno źródło danych z wieloma warstwami

Wiele warstw można połączyć z jednym źródłem danych. Istnieje wiele różnych scenariuszy, w których ta opcja jest przydatna. Rozważmy na przykład scenariusz, w którym użytkownik rysuje wielokąt. Powinniśmy renderować i wypełniać obszar wielokąta, gdy użytkownik dodaje punkty do mapy. Dodanie linii stylowanej w celu nakreślenia wielokąta ułatwia wyświetlanie krawędzi wielokąta, gdy użytkownik rysuje. Aby wygodnie edytować poszczególne pozycje w wielokącie, możemy dodać uchwyt, taki jak pinezka lub znacznik, nad każdą pozycją.

Mapa przedstawiająca wiele warstw renderowania danych z jednego źródła danych

W większości platform mapowania potrzebny jest obiekt wielokątny, obiekt liniowy i pinezka dla każdej pozycji w wielokącie. W miarę modyfikacji wielokąta należy ręcznie zaktualizować wiersz i pinezki, co może szybko stać się złożone.

W przypadku usługi Azure Mapy wystarczy jeden wielokąt w źródle danych, jak pokazano w poniższym kodzie.

//Create a data source and add it to the map.
DataSource source = new DataSource();
map.sources.add(source);

//Create a polygon and add it to the data source.
source.add(Polygon.fromLngLats(/* List of points */));

//Create a polygon layer to render the filled in area of the polygon.
PolygonLayer polygonLayer = new PolygonLayer(source,
    fillColor("rgba(255,165,0,0.2)")
);

//Create a line layer for greater control of rendering the outline of the polygon.
LineLayer lineLayer = new LineLayer(source,
    strokeColor("orange"),
    strokeWidth(2f)
);

//Create a bubble layer to render the vertices of the polygon as scaled circles.
BubbleLayer bubbleLayer = new BubbleLayer(source,
    bubbleColor("orange"),
    bubbleRadius(5f),
    bubbleStrokeColor("white"),
    bubbleStrokeWidth(2f)
);

//Add all layers to the map.
map.layers.add(new Layer[] { polygonLayer, lineLayer, bubbleLayer });
//Create a data source and add it to the map.
val source = DataSource()
map.sources.add(source)

//Create a polygon and add it to the data source.
source.add(Polygon.fromLngLats())

//Create a polygon layer to render the filled in area of the polygon.
val polygonLayer = PolygonLayer(
    source,
    fillColor("rgba(255,165,0,0.2)")
)

//Create a line layer for greater control of rendering the outline of the polygon.
val lineLayer = LineLayer(
    source,
    strokeColor("orange"),
    strokeWidth(2f)
)

//Create a bubble layer to render the vertices of the polygon as scaled circles.
val bubbleLayer = BubbleLayer(
    source,
    bubbleColor("orange"),
    bubbleRadius(5f),
    bubbleStrokeColor("white"),
    bubbleStrokeWidth(2f)
)

//Add all layers to the map.
map.layers.add(arrayOf<Layer>(polygonLayer, lineLayer, bubbleLayer))

Napiwek

Podczas dodawania warstw do mapy przy użyciu map.layers.add metody identyfikator lub wystąpienie istniejącej warstwy można przekazać jako drugi parametr. Spowoduje to, że mapa wstawia nową warstwę dodaną poniżej istniejącej warstwy. Oprócz przekazania identyfikatora warstwy ta metoda obsługuje również następujące wartości.

  • "labels" — Wstawia nową warstwę poniżej warstw etykiet mapy.
  • "transit" - Wstawia nową warstwę poniżej warstwy mapy i tranzytowej.

Następne kroki

Więcej przykładów kodu do dodania do map można znaleźć w następujących artykułach: