Datengesteuerte Formatierung und vieles mehr im neuesten Update für das Azure Maps Web SDK

Veröffentlicht am 24 September, 2018

Senior Technical Program Manager, Azure Maps

Wir freuen uns sehr, das neueste Update für das Azure Maps Web SDK ankündigen zu dürfen. Das Team hat den Sommer über hart daran gearbeitet, viele leistungsstarke Features hinzuzufügen und die Gesamtleistung des Web Maps SDK zu steigern. Hier finden Sie einige der wichtigsten Verbesserungen dieses Updates:

  • Entwicklerzentrierte API-Verbesserungen
  • Neues Modell für Datenquellen und -ebenen
  • Verbinden mehrerer Ebenen mit einer Datenquelle
  • Neue, einfach zu verwaltende Shape-Klasse
  • Datengesteuerte Formatierung von Ebenen
  • Bibliothek für räumliche Berechnungen
  • Unterstützung für räumlich akkurate Kreise

Entwicklerzentrierte API-Verbesserungen

Wir haben unsere API-Schnittstelle intuitiver und leistungsfähiger gestaltet. Bisher wurde ein Großteil der Funktionalität im SDK als Funktionen in der Map-Klasse verfügbar gemacht. Ohne eine Gruppierung der verwandten Funktionen mussten Entwickler häufig fast jede Funktion und Eigenschaft im SDK durchsuchen und hoffen, dass sie die Funktion finden, die sie benötigen. Mit diesem Release haben wir viele verwandte Funktionen miteinander gruppiert und sie über Manager-Eigenschaften in der Map-Klasse verfügbar gemacht. In der letzten Version gab es über 30 Funktionen in der Map-Klasse, und sieben davon bezogen sich auf Datenebenen. In diesem Update werden diese Funktionen sowie viele weitere, die die Arbeit mit Ebenen erleichtern, jetzt über die layers-Eigenschaft der Karte verfügbar gemacht. Wir haben der Karte auch managers-Eigenschaften für Steuerelemente, Ereignisse, das Kartenbild-Sprite, HTML-Marker und Datenquellen hinzugefügt.

Ebenso haben wir eine Option hinzugefügt, mit der sich viele der standardmäßigen SDK-Einstellungen für die Karte direkt im Stammnamespace atlas des SDK festlegen lassen. Auf diese Weise nutzen alle auf einer Seite erstellten Karteninstanzen sowie alle erstellten Dienstclients diese Einstellungen als Standardwerte. Bisher musste für jede Karteninstanz und jeden Dienstclient, die bzw. der Ihrer Anwendung hinzugefügt wurde, während der Initialisierung des Features Ihr Azure Maps-Schlüssel übergeben werden. Das bedeutete, dass Sie ein und dieselbe Einstellung mehrfach in Ihrer Anwendung festlegen mussten – eine mühselige Aufgabe. Indem Sie Ihren Schlüssel im atlas-Stammnamespace festlegen, müssen Sie ihn nur ein einziges Mal in Ihrer Anwendung angeben, was zukünftige Updates wesentlich vereinfacht.

atlas.setSubscriptionKey('Your Azure Maps Key');

Verschiedene weitere Einstellungen wie Informationen zu Sprache und Benutzerregion können im atlas-Stammnamespace ebenfalls als Standardwerte festgelegt werden. Wichtiger Hinweis: Dies sind Standardwerte, die angewendet werden, wenn beim Initialisieren einer Karteninstanz oder eines Dienstclients die entsprechende Option nicht angegeben wird. Wenn Sie beispielsweise beim Initialisieren einer Karte eine andere Sprache übergeben, wird diese statt der Standardsprache verwendet. Dies ist nützlich in Szenarien, in denen Sie auf einer Seite mehrere Karten in verschiedenen Sprachen zeigen möchten.

All diese entwicklerzentrierten Verbesserungen erleichtern die Entwicklung von Anwendungen mir Azure Maps erheblich. Gleichzeitig steigern sie die Leistung und reduzieren die Menge an Code, der für Ihre Anwendung geschrieben werden muss.

Neues Modell für Datenquellen und -ebenen

Bisher ermöglichte das Kartensteuerelement nur das Hinzufügen von räumlichen Vektordaten im GeoJSON-Format zur Karte. Diese Daten wurden auf einer Ebene hinzugefügt, die hinter den Kulissen ihre eigene Datenquelle erstellte und verwaltete. Um Daten auf einer Ebene zu ändern, musste die vorhandene Ebene überschrieben werden – ein ineffizientes Verfahren mit nicht intuitivem Code, wie Sie im folgenden Beispielcode erkennen können.

var myPins = [/* Array filled with pin data */];

//Hinzufügen von Stecknadeln zur Karte.
map.addPins(pins, {
     name: 'MyPinLayer'
});

//Erstellen einer neuen Stecknadel, die der Ebene hinzugefügt werden soll.
var pin = new atlas.data.Feature(new atlas.data.Point(lon, lat));

//Hinzufügen der Stecknadel zum Stecknadelarray.
myPins.push(pin);

//Aktualisieren der Ebene durch Überschreiben aller Daten auf der Ebene. Dies ist kein intuitives Verfahren und erfordert viel Leistung.
map.addPins(pins, {
     name: 'MyPinLayer',  
     overwrite: true
});

In diesem Release haben wir die Datenquelle von der Ebene getrennt. Das bietet eine Reihe von Vorteilen: Sie können eine einzelne Datenquelle unter Verwendung von mehreren Ebenen rendern und gleichzeitig nur eine einzige Instanz der Datenquelle verwalten – so reduzieren Sie den Arbeitsspeicherverbrauch, steigern die Leistung und erstellen eine erheblich leichter zu verstehende API, wie Sie im Beispiel unten sehen können.

//Erstellen einer Datenquelle und Hinzufügen der Datenquelle zur Karte.
var dataSource = new atlas.source.DataSource();
map.sources.add(dataSource);

//Erstellen einer Ebene, die definiert, wie die Formen in der Datenquelle gerendert werden sollen, und Hinzufügen der Ebene zur Karte.
var myPinLayer = new atlas.layer.SymbolLayer(dataSource);
map.layers.add(myPinLayer);

//Hinzufügen von Stecknadeln zur Datenquelle.
dataSource.add([/* Array filled with pin data */]);

//Erstellen einer neuen Stecknadel, die der Karte hinzugefügt werden soll.
var pin = new atlas.data.Feature(atlas.data.Point([lon, lat]));

//Hinzufügen der Nadel zur Datenquelle. Die Karte führt die Aktualisierung automatisch und auf möglichst effiziente Weise durch.
dataSource.add(pin);

Wir haben nicht nur die DataSource-Klasse für mit GeoJSON formatierte Daten hinzugefügt, sondern über eine neue VectorTileSource-Klasse auch Unterstützung für Vektorkacheldienste. Diese Datenquellen können an die folgenden Ebenen angefügt werden, die definieren, auf welche Weise die Daten auf der Karte gerendert werden.

  • Ebene „Blasen“: Punktdaten werden als skalierte Kreise mit Pixelradius gerendert.
  • Ebene „Linien“: Linien und Polygonumrisse werden gerendert.
  • Ebene „Polygon“: Der gefüllte Bereich von Polygonen wird gerendert.
  • Ebene „Symbol“: Punktdaten werden als Symbole und Text gerendert.

Es gibt auch eine TileLayer-Klasse, mit der Sie neben- bzw. untereinander angeordnete Rasterbilder über der Karte einblenden können. Diese Ebene wird nicht an eine Datenquelle angefügt, stattdessen werden die Dienstinformationen der Kachel als Optionen der Ebene angegeben.

Wir haben nicht nur dieses neue Modell für Datenquellen und -ebenen im SDK erstellt, sondern auch die Funktionen und Renderingoptionen für die Visualisierung von Daten auf einer Karte mehr als verdoppelt.

Verbinden mehrerer Ebenen mit einer Datenquelle

Wie bereits erwähnt, können Sie jetzt mehrere Ebenen an die gleiche Datenquelle anfügen. Das mag merkwürdig klingen, ist jedoch in vielen verschiedenen Szenarien sehr nützlich. Nehmen wir als Beispiel ein Szenario, in dem Benutzern das Zeichnen von Polygonen ermöglicht werden soll. Wenn wir einem Benutzer ermöglichen, ein Polygon zu zeichnen, sollten wir den Füllbereich des Polygons rendern, sobald der Benutzer Punkte zur Karte hinzufügt. Durch Hinzufügen einer formatierten Linie für den Umriss des Polygons lassen sich die Kanten des Polygons während des Zeichnens besser erkennen. Wenn wir dann noch oberhalb jeder Position im Polygon einen Ziehpunkt hinzufügen, z.B. eine Stecknadel oder eine andere Markierung, vereinfachen wir damit die Bearbeitung jeder einzelnen Position. Die folgende Abbildung veranschaulicht dieses Szenario.

Verbinden mehrerer Ebenen mit einer Datenquelle

Um dies zu erreichen, müssen Sie auf den meisten Kartenplattformen ein Polygonobjekt, ein Linienobjekt und für jede Position auf dem Polygon eine Stecknadel erstellen. Wenn das Polygon verändert wird, müssen Sie die Linien und Stecknadeln manuell aktualisieren. Der hierfür erforderliche Aufwand wird sehr schnell sehr unübersichtlich.

Mit Azure Maps benötigen Sie nur ein einzelnes Polygon in einer Datenquelle, wie im Code unten gezeigt.

//Erstellen einer Datenquelle und Hinzufügen der Datenquelle zur Karte.
var dataSource = new atlas.source.DataSource();
map.sources.add(dataSource);

//Erstellen eines Polygons und Hinzufügen des Polygons zur Datenquelle.
dataSource.add(new atlas.data.Polygon([[[/* Coordinates for polygon */]]]));

//Erstellen einer Polygonebene zum Rendern des gefüllten Polygonbereichs.
var polygonLayer = new atlas.layer.PolygonLayer(dataSource, 'myPolygonLayer', {
     fillColor: 'rgba(255,165,0,0.2)'
});

//Erstellen einer Linienebene zur besseren Steuerung des Rendervorgangs für den Polygonumriss.
var lineLayer = new atlas.layer.LineLayer(dataSource, 'myLineLayer', {
     color: 'orange',
     width: 2
});

//Erstellen einer Blasenebene zum Rendern der Vertices des Polygons als skalierte Kreise.
var bubbleLayer = new atlas.layer.BubbleLayer(dataSource, 'myBubbleLayer', {
     color: 'orange',
     radius: 5,
     outlineColor: 'white',
     outlineWidth: 2
});

//Hinzufügen aller Ebenen zur Karte.
map.layers.add([polygonLayer, lineLayer, bubbleLayer]);

Sehen Sie sich die Livebeispiele an.

Neue, einfach zu verwaltende Shape-Klasse

Alle vektorbasierten Daten im Azure Maps Web SDK bestehen aus GeoJSON-Objekten, bei denen es sich letztendlich einfach nur um JSON-Objekte handelt, die einem definierten Schema folgen. GeoJSON-Daten weisen allerdings eine Einschränkung auf: Wenn Sie die Daten bearbeiten, werden die Änderungen erst dann auf der Karte sichtbar, wenn Sie das Objekt auf der Karte entfernen und ersetzen. Um das Procedere einfacher und intuitiver zu gestalten, haben wir eine neue Shape-Klasse hinzugefügt, die jedes GeoJSON-Feature und jede GeoJSON-Geometrie umschließen kann. Diese Klasse bietet eine Reihe von Funktionen, die die Aktualisierung von GeoJSON-Daten vereinfachen und Änderungen sofort in der Datenquelle widerspiegeln, der die Shape-Klasse hinzugefügt wurde. Das fanden wir so nützlich, dass wir automatisch alle GeoJSON-Objekte umschließen, die der DataSource-Klasse hinzugefügt werden.

Nehmen wir z.B. ein Szenario, in dem Sie die Position eines Datenpunkts auf der Karte aktualisieren möchten. Bisher mussten Sie die Daten auf der Ebene separat verwalten und dann die Ebene überschreiben, wie im Code unten gezeigt.

//Erstellen einer Stecknadel aus einem Punktfeature.
var pin = new atlas.data.Feature(new atlas.data.Point([-110, 45]));

//Hinzufügen einer Stecknadel zur Karte.
map.addPins([pin], {
     name: 'MyPinLayer'
});

//Aktualisieren der Stecknadelkoordinaten... Die Karte wird nicht aktualisiert.
pin.geometry.coordinates = [-120, 30];

//Überschreiben aller Stecknadeln auf der Ebene, um die Karte zu aktualisieren.
map.addPins([pin], {
     name: 'MyPinLayer',
     overwrite: true
});

Dieser Code ist nicht intuitiv und macht viel mehr Arbeit als nötig. Indem Sie den Datenpunkt mit der Shape-Klasse umschließen, benötigen Sie nur eine Codezeile, um die Position des Datenpunkts auf der Karte zu aktualisieren – wie im folgenden Code gezeigt.

//Erstellen einer Datenquelle und Hinzufügen der Datenquelle zur Karte.
var dataSource = new atlas.source.DataSource();
map.sources.add(dataSource);

//Erstellen einer Ebene, die definiert, wie die Formen in der Datenquelle gerendert werden sollen, und Hinzufügen der Ebene zur Karte.
var myPinLayer = new atlas.layer.SymbolLayer(dataSource);
map.layers.add(myPinLayer);

//Erstellen einer Stecknadel, Umschließen der Stecknadel mit der Shape-Klasse und Hinzufügen der Stecknadel zur Datenquelle.
var pin = new atlas.Shape(new atlas.data.Point([-110, 45]));
dataSource.add(pin);

//Aktualisieren der Stecknadelkoordinaten. Die Karte wird automatisch aktualisiert.
pin.setCoordinates([-120, 30]);

Tipp: Sie können die mit Shape umschlossene Version Ihrer Daten einfach aus der Datenquelle abrufen, anstatt jedes Objekt einzeln zu umschließen.

Datengesteuerte Formatierung von Ebenen

Ein wichtiges neues Feature dieses Updates ist die neue datengesteuerte Formatierung mit Eigenschaftenfunktionen. Mit diesem Feature können Sie Geschäftslogik zu einzelnen Formatierungsoptionen hinzufügen, bei denen die Eigenschaften einbezogen werden, die in jeder einzelnen Form in der angefügten Datenquelle definiert sind. Beim Rendern der Ebene kann auch der Zoomfaktor einbezogen werden. Datengesteuerte Formatierungen reduzieren die Menge an Code, die Sie normalerweise schreiben müssten, und definieren diese Art von Geschäftslogik mithilfe von if-Anweisungen und der Überwachung von Kartenereignissen.

Nehmen wir als Beispiel Daten zu einem Erdbeben. Jeder Datenpunkt hat eine Eigenschaft für die Magnitude. Um die jeweilige Magnitude der einzelnen Datenpunkte auf einer Karte anzuzeigen, können wir mithilfe von BubbleLayer skalierte Kreise zeichnen, für die gilt: Je größer die Magnitude eines Datenpunkts ist, desto größer ist der Radius des Kreises. Der folgende Code veranschaulicht, wie eine datengesteuerte Formatierung auf die Radiusoption von BubbleLayer anwendet wird. Diese Option skaliert den Radius anhand der Magnitudeneigenschaft jedes Datenpunkts auf einem linearen Maßstab von 2 Pixeln und einer Magnitude von 0 bis 40 Pixeln. Der Wert der Magnitude lautet 8. 

var earthquakeLayer = new atlas.layer.BubbleLayer(dataSource, null, {
     radius: ['interpolate', ['linear'], ['get', 'magnitude'],
         0, 2,
         8, 40
     ]
});

Wir könnten auch eine ähnliche datengesteuerte Formatierung anwenden, die die Farbe jedes Kreises definiert und eine Karte wie die folgende generiert.

Datengesteuerte Kartenformatierung

Sehen Sie sich das Livebeispiel an.

Bibliothek für räumliche Berechnungen

Dem Namespace atlas.math wurde eine neue Bibliothek für räumliche Berechnungen hinzugefügt. Diese enthält eine Sammlung nützlicher Berechnungen, die in vielen Kartenanwendungen benötigt werden. Einige Funktionen ermöglichen folgende Berechnungen:

  • Kürzeste Entfernung zwischen Positionen.
  • Länge einer Linie oder eines Pfads.
  • Navigationskurs zwischen Positionen.
  • Entfernungsumrechnungen.
  • Kardinale Splines, mit denen sich schön geglättete Kurvenpfade zwischen mehreren Punkten berechnen lassen.
  • Geodätische Pfade, mit denen sich der direkte Pfad zwischen zwei Punkten unter Berücksichtigung der Erdkrümmung darstellen lässt.
  • Zwischenpositionen entlang eines Pfads.

Sehen Sie sich das Livebeispiel an.

Diese Bibliothek bietet viele einfache und häufig benötigte räumliche Berechnungen. Wenn Sie diffizilere räumliche Berechnungen durchführen müssen, z.B. für geometrische Vereinigungen oder Schnitte, hilft Ihnen die Open Source-Bibliothek Turf.js weiter. Turf.js ist für die direkte Arbeit mit GeoJSON-Daten konzipiert, dem grundlegenden Format für alle Vektordaten in Azure Maps, und lässt sich daher problemlos mit Azure Maps einsetzen.

Unterstützung für räumlich akkurate Kreise

Das GeoJSON-Schema bietet keine standardisierte Möglichkeit, einen räumlich akkuraten Kreis zu definieren. Aus diesem Grund hat das Azure Maps-Team eine allgemeine Möglichkeit standardisiert, um einen räumlich akkuraten Kreis in GeoJSON zu definieren, ohne das Schema zu zerstören. Näheres dazu finden Sie in unserer Dokumentation. Sie können GeoJSON-Objekte mithilfe von reinem JSON im Azure Maps-Websteuerelement oder unter Verwendung der Hilfsklassen im Namespace atlas.data definieren. Im Folgenden sehen Sie ein Beispiel für die Definition eines Kreises mit einem Radius von 1.000 Metern über Seattle.

Mit reinem JSON

var circle = {
     "type": "Feature",
     "geometry": {
         "type": "Point",
         "coordinates": [-122.33, 47.6]
     },
     "properties": {
         "subType": "Circle",
         "radius": 1000
     }
};

Mit Hilfsklassen im Namespace „atlas.data“

var circle = new atlas.data.Feature(new atlas.data.Point([-122.33, 47.6]), {
     subType: "Circle",
     radius: 1000
});

Beim Rendern dieser Kreise konvertiert das Azure Maps-Websteuerelement diese Punktfeature in ein kreisförmiges Polygon, das mit vielen der verschiedenen Renderingebenen verwendet werden kann. Im Folgenden sehen Sie eine Karte, auf der der Kreis als gefülltes Polygon gerendert wurde.

Karte von Seattle

Sehen Sie sich das Livebeispiel an.

Ein wichtiger Unterschied zwischen räumlich akkuraten Kreisen und durch BubbleLayer generierten Kreisen besteht darin, dass die Blasenebene jeder Blase einen Pixelradius zuweist. Wenn der Benutzer die Karte zoomt, ändert sich der Pixelradius nicht, daher ändert sich der Kartenbereich, der durch die Blase abgedeckt ist. Bei einem räumlich akkuraten Kreis sind die Vertices an Koordinaten auf der Karte gebunden. Wenn die Karte gezoomt wird, wird der Kreis ebenfalls skaliert und deckt immer den gleichen Bereich ab.

Wichtiger Hinweis: Diese Kreise sehen aufgrund der Mercator-Projektion, die von der Karte verwendet wird, möglicherweise nicht immer kreisrund aus. Je näher ein Kreis am Nord- oder Südpol liegt, desto größer und ellipsenförmiger sieht er aus. Das Gebiet, das er auf einem Globus repräsentieren würde, ist jedoch kreisrund. Die folgende Karte zeigt zwei Kreise mit einem Radius von jeweils 750 km (750.000 Meter). Ein Kreis wird über Grönland gerendert, das sehr nah am Nordpol liegt, der andere über Brasilien in der Nähe des Äquators.

Azure Maps – Beispiel für geografische Kreise

Sehen Sie sich das Livebeispiel an.

Abwärtskompatibilität

Wenn Sie bereits eine App mit Azure Maps entwickelt haben, fragen Sie sich sicherlich, ob Sie die gesamte Anwendung jetzt neu schreiben müssen. Die Antwort lautet „Nein“. Wir haben alles daran gesetzt, die Abwärtskompatibilität beizubehalten. Wir haben viele der alten Funktionen in der Dokumentation als „veraltet“ markiert, um Entwickler davon abzuhalten, sie in neuen Anwendungen zu verwenden. Aber wir unterstützen diese Features weiterhin so, wie sie in Version 1 des SDK vorkommen.

Wir sind allerdings auf einige Anwendungen gestoßen, bei denen bei Verwendung des Kartensteuerelements ein wichtiger Schritt ausgelassen wurde. Wenn eine Instanz des Kartensteuerelements erstellt wird, müssen verschiedene Ressourcen geladen werden, wie z.B. eine Web-GL-Canvas. Das geschieht ziemlich schnell, aber asynchron. Das bedeutet, dass die nächste Codezeile nach dem Erstellen der Karteninstanz möglicherweise schon aufgerufen wird, bevor die Karte fertig geladen ist. Wenn diese Codezeile versucht, vor Beendigung des Ladevorgangs mit der Karte zu interagieren, kann ein Fehler auftreten. Um dieses Problem zu beheben, sollte das Ladeereignis an die Karte angefügt werden. Zudem sollte die Funktion, die nach dem Laden der Karte ausgeführt werden muss, zum Rückruf des Ereignisses hinzugefügt werden. Wenn Sie das Ladeereignis der Karte nicht verwenden, kann es zurzeit passieren, dass Ihre Anwendung die meiste Zeit zwar ordnungsgemäß funktioniert, auf einigen Benutzergeräten jedoch nicht. Der folgende Code veranschaulicht das Problem und zeigt die Lösung dafür.

Problem

//Initialisieren einer Karteninstanz.
var map = new atlas.Map('myMap', {
     'subscription-key': 'Your Azure Maps Key'
});

//Zusätzlicher Code, der mit der Karte interagiert. Die Karte ist möglicherweise noch nicht fertig geladen.

Lösung mit einer älteren API (weiterhin unterstützt)

//Initialisieren einer Karteninstanz.
var map = new atlas.Map('myMap', {
     'subscription-key': 'Your Azure Maps Key'
});

//Warten, bis die Kartenressourcen vollständig geladen sind.
map.addEventListener("load", function (e) {
     //Add your additional code that interacts with the map here.
});

Lösung mit der neuen API

//Hinzufügen des Azure Maps-Abonnementschlüssels zum Karten-SDK.
atlas.setSubscriptionKey('Your Azure Maps Key');

//Initialisieren einer Karteninstanz.
var map = new atlas.Map('myMap');

//Warten, bis die Kartenressourcen vollständig geladen sind.
map.events.add('load', function (e) {
     //Add your additional code that interacts with the map here.
});

Teilen Sie uns Ihre Meinung mit!

Wir arbeiten beständig daran, die Azure Maps-Plattform zu verbessern und zu erweitern, und freuen uns über Ihr Feedback.

  • Möchten Sie ein Feature anfordern? Posten Sie die Anforderung auf unserer Feedbackwebsite, oder stimmen Sie dort für Features ab.
  • Haben Sie ein Problem mit Kartendaten entdeckt? Senden Sie es über das Map Share Reporter-Tool von TomTom direkt an unseren Datenanbieter.
  • Funktioniert Ihr Code nicht so, wie er soll? Möchten Sie, dass wir uns im Azure-Blog mit einem bestimmten Thema beschäftigen? Fragen Sie uns in den Azure Maps-Foren. Wir helfen Ihnen gerne und möchten sicherstellen, dass Sie die Azure Maps-Plattform optimal nutzen können.
  • Suchen Sie nach Codebeispielen, oder haben Sie selbst Code geschrieben, den Sie mit anderen teilen möchten? Besuchen Sie uns auf GitHub.