Skapa en datakälla (Android SDK)

Azure Kartor Android SDK lagrar data i datakällor. Med hjälp av datakällor optimeras dataåtgärderna för frågor och rendering. Det finns för närvarande två typer av datakällor:

  • GeoJSON-källa: Hanterar rådata för platser i GeoJSON-format lokalt. Bra för små till medelstora datamängder (upp till hundratusentals former).
  • Vektorpanelkälla: Läser in data formaterade som vektorpaneler för den aktuella kartvyn, baserat på kartpanelssystemet. Perfekt för stora till stora datamängder (miljontals eller miljarder former).

GeoJSON-datakälla

Azure Kartor använder GeoJSON som en av sina primära datamodeller. GeoJSON är en öppen geospatial standard för att representera geospatiala data i JSON-format. GeoJSON-klasser som är tillgängliga i Azure Kartor Android SDK för att enkelt skapa och serialisera GeoJSON-data. Läs in och lagra GeoJSON-data i DataSource klassen och rendera dem med hjälp av skikt. Följande kod visar hur GeoJSON-objekt kan skapas i Azure Kartor.

/*
    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)

Tips

GeoJSON-data kan läggas till i DataSource en instans med någon av tre metoder: , och add importDataFromUrl setShapes . Metoden setShapes är ett effektivt sätt att skriva över alla data i en datakälla. Om du anropar metoderna then för att ersätta alla data i clear add en datakälla görs två renderings-anrop till kartan. Metoden setShape rensar och lägger till data i datakällan med ett enda renderings-anrop till kartan.

Alternativt kan egenskaperna läsas in i ett JsonObject först och sedan skickas till funktionen när du skapar den, enligt nedan.

//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)

När du har skapat en GeoJSON-funktion kan en datakälla läggas till på kartan via sources egenskapen för kartan. Följande kod visar hur du skapar en DataSource , lägger till den på kartan och lägger till en funktion i datakällan.

//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);

Följande kod visar flera sätt att skapa en GeoJSON-funktion, FeatureCollection och geometrier.

//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)

Serialisera och deserialisera GeoJSON

Funktionssamlingen, funktions- och geometriklasserna har fromJson() toJson() statiska metoder som hjälper till med serialisering. Den formaterade giltiga JSON-strängen som fromJson() skickas via metoden skapar geometriobjektet. Den fromJson() här metoden innebär också att du kan använda Gson eller andra serialiserings-/deserialiseringsstrategier. Följande kod visar hur du tar en strängifierad GeoJSON-funktion och deserialiserar den till klassen Feature och sedan serialiserar den tillbaka till en GeoJSON-sträng.

//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()

Importera GeoJSON-data från webb- eller tillgångsmappen

De flesta GeoJSON-filer innehåller en FeatureCollection. Läs GeoJSON-filer som strängar och använd metoden FeatureCollection.fromJson för att deserialisera den.

Klassen har en inbyggd metod som heter som kan läsa in GeoJSON-filer med hjälp av en URL till en fil på webben eller DataSource importDataFromUrl i tillgångsmappen. Den här metoden måste anropas innan datakällan läggs till på kartan.

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)

Metoden är ett enkelt sätt att läsa in ett GeoJSON-flöde i en datakälla, men ger begränsad kontroll över hur data läses in och vad som händer när de har importDataFromUrl lästs in. Följande kod är en återanvändbar klass för att importera data från webb- eller tillgångsmappen och returnera dem till UI-tråden via en återanropsfunktion. I motringningen kan du sedan lägga till ytterligare logik efter inläsningen för att bearbeta data, lägga till dem på kartan, beräkna dess begränsningsruta och uppdatera kartkameran.

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)
                    }
                }
            }
        }
    }
}

Koden nedan visar hur du använder det här verktyget för att importera GeoJSON-data som en sträng och returnera dem till UI-tråden via ett återanrop. I motringning kan strängdata serialiseras till en GeoJSON-funktionssamling och läggas till i datakällan. Du kan också uppdatera kartkameran för att fokusera på data.

//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)
        )
    }

Uppdatera en funktion

Klassen DataSource gör det enkelt att lägga till och ta bort funktioner. Om du vill uppdatera geometrin eller egenskaperna för en funktion måste du ersätta funktionen i datakällan. Det finns två metoder som kan användas för att uppdatera en eller flera funktioner:

  1. Skapa de nya funktionerna med önskade uppdateringar och ersätt alla funktioner i datakällan med hjälp av setShapes metoden . Den här metoden fungerar bra när du vill uppdatera alla funktioner i en datakälla.
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. Håll reda på funktionsinstansen i en variabel och skicka den till metoden för remove datakällor för att ta bort den. Skapa nya funktioner med önskade uppdateringar, uppdatera variabelreferensen och lägg till den i datakällan med hjälp av add metoden .
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)
}

Tips

Om du har vissa data som kommer att uppdateras regelbundet och andra data som sällan ändras, är det bäst att dela upp dem i separata datakällsinstanser. När en uppdatering sker i en datakälla tvingar den kartan att ompaint alla funktioner i datakällan. Genom att dela upp dessa data skulle endast de funktioner som uppdateras regelbundet ommålas när en uppdatering sker i den ena datakällan medan funktionerna i den andra datakällan inte behöver ompainteras. Detta hjälper till med prestanda.

Vektorpanelkälla

En vektorpanelkälla beskriver hur du kommer åt ett vektorpanelslager. Använd klassen VectorTileSource för att instansiera en vektorpanelkälla. Vektorpanelskikt liknar panelskikt, men de är inte desamma. Ett panelskikt är en textbild. Vektorpanellager är en komprimerad fil i PBF-format. Den här komprimerade filen innehåller vektorkartadata och ett eller flera skikt. Filen kan renderas och formateras på klienten, baserat på formatet för varje lager. Data i en vektorpanel innehåller geografiska funktioner i form av punkter, linjer och polygoner. Det finns flera fördelar med att använda vektorpanelsskikt i stället för panelskikt för fönster:

  • En filstorlek på en vektorpanel är vanligtvis mycket mindre än en motsvarande ruta. Därför används mindre bandbredd. Det innebär kortare svarstider, en snabbare karta och en bättre användarupplevelse.
  • Eftersom vektorpaneler återges på klienten anpassas de till upplösningen på enheten som de visas på. Därför visas de renderade kartorna mer väldefinierade, med genomskinliga etiketter.
  • Att ändra dataformatet i vektorkartorna kräver inte att data laddas ned igen, eftersom det nya formatet kan tillämpas på klienten. Om du däremot ändrar stilen på ett fönsterskikt måste du vanligtvis läsa in paneler från servern och sedan använda det nya formatet.
  • Eftersom data levereras i vektorform krävs mindre bearbetning på serversidan för att förbereda data. Det innebär att nyare data kan göras tillgängliga snabbare.

Azure Kartor följer Mapbox Vector Tile Specification, en öppen standard. Azure Kartor tillhandahåller följande vektorpaneler som en del av plattformen:

Tips

När du använder vektor- eller Kartor bildpaneler från Azure Kartor rendera tjänsten med webb-SDK:n kan du ersätta atlas.microsoft.com med platshållaren azmapsdomain.invalid . Platshållaren ersätts med samma domän som används av kartan och lägger automatiskt till samma autentiseringsinformation. Detta förenklar avsevärt autentiseringen med renderingstjänsten vid användning Azure Active Directory autentisering.

Om du vill visa data från en vektorpanelkälla på kartan ansluter du källan till ett av datarenderingsskikten. Alla lager som använder en vektorkälla måste ange sourceLayer ett värde i alternativen. Följande kod läser in Azure Kartor för trafikflödesvektor som en vektorpanelkälla och visar den sedan på en karta med hjälp av ett linjeskikt. Den här vektorpanelkällan har en enda uppsättning data i källskiktet som kallas "Trafikflöde". Raddata i den här datauppsättningen har en egenskap som kallas och som används i den här koden för att välja traffic_level färg och skala radstorleken.

//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")

Karta med färgkodade väglinjer som visar trafikflödesnivåer

Ansluta en datakälla till ett lager

Data återges på kartan med hjälp av renderingslager. En enskild datakälla kan refereras till av ett eller flera renderingslager. Följande renderingslager kräver en datakälla:

  • Bubbelskikt – renderar punktdata som skalade cirklar på kartan.
  • Symbolskikt – återger punktdata som ikoner eller text.
  • Skikt på en värmekarta – renderar punktdata som en densitets heat map.
  • Linjeskikt – rendera en linje och eller rendera konturen av polygoner.
  • Polygonskikt – fyller området i en polygon med en solid färg eller ett bildmönster.

Följande kod visar hur du skapar en datakälla, lägger till den på kartan och ansluter den till ett bubbelskikt. Importera sedan GeoJSON-punktdata från en fjärrplats till datakällan.

//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)

Det finns ytterligare renderingslager som inte ansluter till dessa datakällor, men de läser in data direkt för rendering.

  • Panelskikt – lägger över ett kartskikt ovanpå kartan.

En datakälla med flera lager

Flera lager kan anslutas till en enda datakälla. Det finns många olika scenarier där det här alternativet är användbart. Tänk dig till exempel det scenario där en användare ritar en polygon. Vi bör rendera och fylla polygonområdet när användaren lägger till punkter på kartan. Om du lägger till en formaterad linje för att beskriva polygonen blir det enklare att se polygonens kanter, allt eftersom användaren drar. För att enkelt redigera en enskild position i polygonen kan vi lägga till en referens, till exempel ett stift eller en markör, ovanför varje position.

Karta som visar flera skikt som återger data från en enda datakälla

I de flesta mappningsplattformar behöver du ett polygonobjekt, ett linjeobjekt och en nål för varje position i polygonen. När polygonen ändras skulle du behöva uppdatera raden och stiften manuellt, vilket snabbt kan bli komplext.

Med Azure Kartor är allt du behöver en enda polygon i en datakälla, som du ser i koden nedan.

//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))

Tips

När du lägger till skikt på kartan med hjälp av metoden kan ID:t eller instansen för ett befintligt map.layers.add lager skickas som en andra parameter. Detta skulle ange att kartan ska infoga det nya skiktet som läggs till under det befintliga skiktet. Förutom att skicka ett lager-ID stöder den här metoden även följande värden.

  • "labels" – Infogar det nya skiktet under kartetikettlagren.
  • "transit" – Infogar det nya skiktet under kartvägs- och transportlagren.

Nästa steg

I följande artiklar finns fler kodexempel att lägga till i dina kartor: