Sdílet prostřednictvím


Vytvoření zdroje dat v sadě iOS SDK (Preview)

Poznámka:

Vyřazení sady Azure Mapy iOS SDK

Sada Azure Mapy Native SDK pro iOS je teď zastaralá a bude vyřazena 31. 31. 25. Pokud se chcete vyhnout přerušení služeb, proveďte migraci do sady Azure Mapy Web SDK do 31. 31. 25. Další informace najdete v průvodci migrací sady Azure Mapy iOS SDK.

Sada Azure Mapy iOS SDK ukládá data do zdrojů dat. Použití zdrojů dat optimalizuje operace s daty pro dotazování a vykreslování. V současné době existují dva typy zdrojů dat:

  • Zdroj GeoJSON: Spravuje nezpracovaná data o poloze v místním formátu GeoJSON. Vhodné pro malé až střední datové sady (nahoru ze stovek tisíc obrazců).
  • Zdroj vektorové dlaždice: Načte data formátovaná jako vektorové dlaždice pro aktuální zobrazení mapy na základě systému provazování map. Ideální pro velké až masivní datové sady (miliony nebo miliardy obrazců).

Zdroj dat GeoJSON

Azure Mapy používá GeoJSON jako jeden z jeho primárních datových modelů. GeoJSON je otevřený geoprostorový standardní způsob reprezentace geoprostorových dat ve formátu JSON. Třídy GeoJSON dostupné v sadě Azure Mapy iOS SDK pro snadné vytváření a serializaci dat GeoJSON. Načtěte a uložte data GeoJSON do DataSource třídy a vykreslujte je pomocí vrstev. Následující kód ukazuje, jak je možné v Azure Mapy vytvářet objekty GeoJSON.

/*
    Raw GeoJSON feature

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

*/

//Create a point feature.
let feature = Feature(Point(CLLocationCoordinate2D(latitude: 45, longitude: -100)))

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

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

Alternativně lze vlastnosti načíst do slovníku (JSON) a pak předat funkci při jeho vytváření, jak ukazuje následující kód:

//Create a dictionary to store properties for the feature.
var properties: [String: Any] = [:]
properties["custom-property"] = "value"

let feature = Feature(Point(CLLocationCoordinate2D(latitude: 45, longitude: -100)), properties: properties)

Jakmile vytvoříte funkci GeoJSON, můžete zdroj dat přidat do mapy prostřednictvím sources vlastnosti mapy. Následující kód ukazuje, jak vytvořit DataSource, přidat do mapy a přidat do zdroje dat funkci.

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

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

Následující kód ukazuje několik způsobů, jak vytvořit GeoJSON Feature, FeatureCollectiona geometrie.

// GeoJSON Point Geometry
let point = Point(location)

// GeoJSON LineString Geometry
let polyline = Polyline(locations)

// GeoJSON Polygon Geometry
let polygon = Polygon(locations)

let polygonWithInteriorPolygons = Polygon(locations, interiorPolygons: polygons)

// GeoJSON MultiPoint Geometry
let pointCollection = PointCollection(locations)

// GeoJSON MultiLineString Geometry
let multiPolyline = MultiPolyline(polylines)

let multiPolylineFromLocations = MultiPolyline(locations: arrayOfLocationArrays) // [[CLLocationCoordinate2D]]

// GeoJSON MultiPolygon Geometry
let multiPolygon = MultiPolygon(polygons)

let multiPolygonFromLocations = MultiPolygon(locations: arrayOfLocationArrays) // [[CLLocationCoordinate2D]]

// GeoJSON GeometryCollection Geometry

let geometryCollection = GeometryCollection(geometries)

// GeoJSON Feature
let pointFeature = Feature(Point(location))

// GeoJSON FeatureCollection
let featureCollection = FeatureCollection(features)

Serializace a deserializace GeoJSON

Kolekce funkcí, funkce a geometrie třídy mají všechny fromJson(_:) a toJson() statické metody, které pomáhají se serializací. Formátovaný platný řetězec JSON předaný metodou fromJson() vytvoří objekt geometrie. Tato fromJson() metoda také znamená, že můžete použít JSONSerialization nebo jiné strategie serializace/deserializace. Následující kód ukazuje, jak vzít řetězcovou geoJSON funkci a deserializovat ji do Feature třídy a pak ji serializovat zpět do řetězce GeoJSON.

// Take a stringified GeoJSON object.
let geoJSONString = """
    {
        "type": "Feature",
        "geometry": {
            "type": "Point",
            "coordinates": [-100, 45]
        },
        "properties": {
            "custom-property": "value"
        }
    }
"""

// Deserialize the JSON string into a feature.
guard let feature = Feature.fromJson(geoJSONString) else {
    throw GeoJSONSerializationError.couldNotSerialize
}

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

Import dat GeoJSON z webové složky nebo složky assetů

Většina souborů GeoJSON obsahuje .FeatureCollection Přečtěte si soubory GeoJSON jako řetězce a použijte metodu FeatureCollection.fromJson(_:) k deserializaci.

Třída DataSource má integrovanou metodu, importData(fromURL:) která může načíst soubory GeoJSON pomocí adresy URL k souboru na webu nebo zařízení.

// Create a data source.
let source = DataSource()

// Import the geojson data and add it to the data source.
let url = URL(string: "URL_or_FilePath_to_GeoJSON_data")!
source.importData(fromURL: url)

// Examples:
// source.importData(fromURL: URL(string: "asset://sample_file.json")!)
// source.importData(fromURL: URL(string: "https://example.com/sample_file.json")!)

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

Tato importData(fromURL:) metoda poskytuje způsob, jak načíst geoJSON kanál do zdroje dat, ale poskytuje omezenou kontrolu nad tím, jak se data načtou a co se stane po načtení. Následující kód je opakovaně použitelná třída pro import dat z webové složky nebo složky assetů a vrácení do vlákna uživatelského rozhraní prostřednictvím funkce zpětného volání. V zpětném volání pak můžete přidat další logiku následného načtení pro zpracování dat, přidat je do mapy, vypočítat jeho ohraničující pole a aktualizovat kameru mapy.

import Foundation

@objc
public class Utils: NSObject {
    /// Imports data from a web url or local file url and returns it as a string to a callback on the main thread.
    /// - Parameters:
    ///     - url: A web url or local file url that points to data to load.
    ///     - completion: The callback function to return the data to.
    @objc
    public static func importData(fromURL url: URL, completion: @escaping (String?) -> Void) {
        URLSession.shared.dataTask(with: url) { data, _, _ in
            DispatchQueue.main.async {
                if let data = data {
                    completion(String(decoding: data, as: UTF8.self))
                } else {
                    completion(nil)
                }
            }
        }.resume()
    }
}

Následující kód ukazuje, jak pomocí tohoto nástroje importovat data GeoJSON jako řetězec a vrátit je do hlavního vlákna prostřednictvím zpětného volání. V zpětném volání lze řetězcová data serializovat do kolekce funkcí GeoJSON a přidat do zdroje dat. Volitelně můžete aktualizovat kameru mapy, aby se fokus zaměřil na data.

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

// Create a web url or a local file url
let url = URL(string: "URL_to_GeoJSON_data")!
// Examples:
// let url = Bundle.main.url(forResource: "FeatureCollectionSample", withExtension: "geojson")!
// let url = URL(string: "www.yourdomain.com/path_to_feature_collection_sample")!

// Import the geojson data and add it to the data source.
Utils.importData(fromURL: url) { result in
    guard let result = result else {
        // No data imported.
        return
    }

    // Parse the data as a GeoJSON Feature Collection.
    guard let fc = FeatureCollection.fromJson(result) else {
        // Invalid data for FeatureCollection type.
        return
    }

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

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

    // Calculate the bounding box of all the data in the Feature Collection.
    guard let bbox = BoundingBox.fromData(fc) else {
        // The feature collection is empty.
        return
    }

    // Update the maps camera so it is focused on the data.
    map.setCameraBoundsOptions([
        .bounds(bbox),
        .padding(20)
    ])
}

Aktualizace funkce

Třída DataSource usnadňuje přidávání a odebírání funkcí. Aktualizace geometrie nebo vlastností funkce vyžaduje nahrazení funkce ve zdroji dat. Existují dvě metody, které lze použít k aktualizaci funkcí:

  1. Vytvořte nové funkce s požadovanými aktualizacemi a nahraďte všechny funkce ve zdroji dat metodou set . Tato metoda funguje dobře, když chcete aktualizovat všechny funkce ve zdroji dat.
var source: DataSource!

private func 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.
    let myFeature = Feature(Point(CLLocationCoordinate2D(latitude: 0, longitude: 0)))
    myFeature.addProperty("Name", value: "Original value")
    source.add(feature: myFeature)
}

private func updateFeature() {
    // Create a new replacement feature with an updated geometry and property value.
    let myNewFeature = Feature(Point(CLLocationCoordinate2D(latitude: -10, longitude: 10)))
    myNewFeature.addProperty("Name", value: "New value")

    // Replace all features to the data source with the new one.
    source.set(feature: myNewFeature)
}
  1. Sledujte instanci funkce v proměnné a předejte ji do metody zdrojů remove dat, abyste ji odebrali. Vytvořte nové funkce s požadovanými aktualizacemi, aktualizujte odkaz na proměnnou a přidejte ji do zdroje dat pomocí add metody.
var source: DataSource!
var myFeature: Feature!

private func 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(Point(CLLocationCoordinate2D(latitude: 0, longitude: 0)))
    myFeature.addProperty("Name", value: "Original value")
    source.add(feature: myFeature)
}

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

    // Get properties from original feature.
    var props = myFeature.properties

    // Update a property.
    props["Name"] = "New value"

    // Create a new replacement feature with an updated geometry.
    myFeature = Feature(
        Point(CLLocationCoordinate2D(latitude: -10, longitude: 10)),
        properties: props
    )

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

Tip

Pokud máte nějaká data, která se budou pravidelně aktualizovat, a jiná data, která se zřídka změní, je nejlepší je rozdělit na samostatné instance zdroje dat. Když dojde k aktualizaci ve zdroji dat, vynutí mapování překreslit všechny funkce ve zdroji dat. Rozdělením těchto dat by se při aktualizaci v jednom zdroji dat překreslily pouze funkce, které se pravidelně aktualizují, zatímco funkce v druhém zdroji dat by se nemusely překreslit. To pomáhá s výkonem.

Zdroj vektorové dlaždice

Zdroj vektorové dlaždice popisuje, jak získat přístup k vrstvě vektorové dlaždice. VectorTileSource Pomocí třídy vytvořte instanci zdroje vektorové dlaždice. Vrstvy vektorových dlaždic jsou podobné vrstvě dlaždic, ale nejsou stejné. Vrstva dlaždice je rastrový obrázek. Vrstvy vektorových dlaždic jsou komprimovaný soubor ve formátu PBF . Tento komprimovaný soubor obsahuje data vektorového mapování a jednu nebo více vrstev. Soubor lze vykreslit a stylovat v klientovi na základě stylu každé vrstvy. Data v dlaždici vektoru obsahují geografické funkce ve formě bodů, čar a mnohoúhelníku. Použití vrstev vektorových dlaždic místo rastrových vrstev dlaždic má několik výhod:

  • Velikost souboru vektorové dlaždice je obvykle mnohem menší než ekvivalentní rastrová dlaždice. Proto se používá menší šířka pásma. To znamená nižší latenci, rychlejší mapování a lepší uživatelské prostředí.
  • Vzhledem k tomu, že se vektorové dlaždice vykreslují na klientovi, přizpůsobí se rozlišení zařízení, na kterém se zobrazují. V důsledku toho se vykreslené mapy zobrazují jasněji definované s krystalickými popisky.
  • Změna stylu dat v vektorových mapách nevyžaduje opětovné stažení dat, protože nový styl lze použít v klientovi. Změna stylu rastrové vrstvy dlaždic naproti tomu obvykle vyžaduje načtení dlaždic ze serveru a následné použití nového stylu.
  • Vzhledem k tomu, že data jsou dodávána ve formě vektoru, je k přípravě dat potřeba méně zpracování na straně serveru. V důsledku toho je možné novější data zpřístupnit rychleji.

Azure Mapy dodržuje specifikaci vektorové dlaždice Mapbox, otevřeného standardu. Azure Mapy poskytuje jako součást platformy následující služby vektorových dlaždic:

Tip

Při použití dlaždic vektorových nebo rastrových obrázků ze služby Azure Mapy render pomocí sady SDK pro iOS můžete nahradit atlas.microsoft.comAzureMapvlastností "s"domainPlaceholder. Tento zástupný symbol se nahradí stejnou doménou, kterou mapa používá, a automaticky připojí stejné ověřovací údaje. To výrazně zjednodušuje ověřování pomocí služby render při použití ověřování Microsoft Entra.

Pokud chcete zobrazit data ze zdroje vektorové dlaždice na mapě, připojte zdroj k jedné z vrstev vykreslování dat. Všechny vrstvy, které používají vektorový zdroj, musí v možnostech zadat sourceLayer hodnotu. Následující kód načte službu dlaždic vektoru toku provozu Azure Mapy jako zdroj vektorové dlaždice a pak ji zobrazí na mapě pomocí vrstvy čáry. Tento zdroj vektorové dlaždice má jednu sadu dat ve zdrojové vrstvě s názvem "Tok provozu". Řádková data v této sadě dat mají vlastnost, traffic_level která se používá v tomto kódu k výběru barvy a měřítka velikosti řádků.

// Formatted URL to the traffic flow vector tiles.
let trafficFlowUrl = "\(map.domainPlaceholder)/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.
let source = VectorTileSource(options: [
    .tiles([trafficFlowUrl]),
    .maxSourceZoom(22)
])
map.sources.add(source)

// Create a layer for traffic flow lines.
let layer = LineLayer(
    source: source,
    options: [

        // 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(
            from: NSExpression(
                forAZMInterpolating: NSExpression(forKeyPath: "traffic_level"),
                curveType: .linear,
                parameters: nil,
                stops: NSExpression(forConstantValue: [
                    0: UIColor.red,
                    0.33: UIColor.yellow,
                    0.66: UIColor.green
                ])
            )
        ),

        // Scale the width of roads based on the traffic_level property.
        .strokeWidth(
            from: NSExpression(
                forAZMInterpolating: NSExpression(forKeyPath: "traffic_level"),
                curveType: .linear,
                parameters: nil,
                stops: NSExpression(forConstantValue: [
                    0: 6,
                    1: 1
                ])
            )
        )
    ]
)

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

Snímek obrazovky mapy s barevnými směrovými čárami znázorňujícími úrovně toku provozu

Připojení zdroj dat do vrstvy

Data se na mapě vykreslují pomocí vykreslovacích vrstev. Jedna nebo více vrstev vykreslování může odkazovat na jeden zdroj dat. Následující vrstvy vykreslování vyžadují zdroj dat:

  • Bublinová vrstva – vykreslí data bodů jako škálované kruhy na mapě.
  • Vrstva symbolu – vykreslí data bodů jako ikony nebo text.
  • Vrstva heat mapy – vykresluje data bodů jako heat mapu hustoty.
  • Vrstva čáry – vykreslení čáry a vykreslení obrysu mnohoúhelníku
  • Polygonová vrstva – vyplní oblast mnohoúhelníku plnou barvou nebo vzorem obrázku.

Následující kód ukazuje, jak vytvořit zdroj dat, přidat ho do mapy, importovat data bodu GeoJSON ze vzdáleného umístění do zdroje dat a pak ho připojit k bublinové vrstvě.

// Create a data source.
let source = DataSource()

// Create a web url or a local file url
let url = URL(string: "URL_or_FilePath_to_GeoJSON_data")!
// Examples:
// let url = Bundle.main.url(forResource: "FeatureCollectionSample", withExtension: "geojson")!
// let url = URL(string: "yourdomain.com/path_to_feature_collection_sample")!

// Import the geojson data and add it to the data source.
source.importData(fromURL: url)

// 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.
let layer = BubbleLayer(source: source)
map.layers.addLayer(layer)

Existují další vrstvy vykreslování, které se k těmto zdrojům dat nepřipojují, ale přímo načítají data pro vykreslování.

  • Vrstva dlaždic – superimpozizuje rastrovou vrstvu dlaždic v horní části mapy.

Jeden zdroj dat s více vrstvami

K jednomu zdroji dat je možné připojit více vrstev. Tato možnost je užitečná v mnoha různých scénářích. Představte si například scénář, ve kterém uživatel nakreslí mnohoúhelník. Měli bychom vykreslit a vyplnit mnohoúhelník, protože uživatel přidává body do mapy. Když přidáte stylovanou čáru k obrysu mnohoúhelníku, bude se snadněji zobrazovat okraje mnohoúhelníku, jak uživatel nakreslí. Pokud chceme pohodlně upravit jednotlivou pozici v mnohoúhelníku, můžeme nad každou pozici přidat úchyt, například špendlík nebo značku.

Snímek obrazovky mapy zobrazující více vrstev vykreslující data z jednoho zdroje dat

Ve většině mapovacích platforem byste potřebovali polygonový objekt, spojnicový objekt a špendlík pro každou pozici v mnohoúhelníku. Při úpravě mnohoúhelníku byste museli ručně aktualizovat čáru a špendlíky, což se může rychle stát složitým.

S Azure Mapy stačí jen jeden mnohoúhelník ve zdroji dat, jak je znázorněno v následujícím kódu.

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

// Create a polygon and add it to the data source.
source.add(geometry: Polygon([
    CLLocationCoordinate2D(latitude: 33.15, longitude: -104.5),
    CLLocationCoordinate2D(latitude: 38.5, longitude: -113.5),
    CLLocationCoordinate2D(latitude: 43, longitude: -111.5),
    CLLocationCoordinate2D(latitude: 43.5, longitude: -107),
    CLLocationCoordinate2D(latitude: 43.6, longitude: -94)
]))

// Create a polygon layer to render the filled in area of the polygon.
let polygonLayer = PolygonLayer(
    source: source,
    options: [.fillColor(UIColor(red: 1, green: 165/255, blue: 0, alpha: 0.2))]
)

// Create a line layer for greater control of rendering the outline of the polygon.
let lineLayer = LineLayer(source: source, options: [
    .strokeColor(.orange),
    .strokeWidth(2)
])

// Create a bubble layer to render the vertices of the polygon as scaled circles.
let bubbleLayer = BubbleLayer(
    source: source,
    options: [
        .bubbleColor(.orange),
        .bubbleRadius(5),
        .bubbleStrokeColor(.white),
        .bubbleStrokeWidth(2)
    ]
)

// Add all layers to the map.
map.layers.addLayers([polygonLayer, lineLayer, bubbleLayer])

Tip

Můžete také použít map.layers.insertLayer(_:below:) metodu, kde ID nebo instance existující vrstvy lze předat jako druhý parametr. To by řeklo, že mapa vloží novou vrstvu, která se přidá pod existující vrstvu. Kromě předávání ID vrstvy tato metoda podporuje také následující hodnoty.

  • "labels" - Vloží novou vrstvu pod vrstvy popisků mapy.
  • "transit" - Vloží novou vrstvu pod vrstvu silniční a tranzitní vrstvy mapy.

Další informace

Další ukázky kódu pro přidání do map najdete v následujících článcích: