Passer la navigation

Style axé sur les données et plus dans la dernière mise à jour du kit SDK web Azure Maps

Publié le 24 septembre, 2018

Senior Technical Program Manager, Azure Maps

C’est avec grand plaisir que nous annonçons la dernière mise à jour du kit SDK web Azure Maps. L’équipe a travaillé sans relâche au cours de l’été pour ajouter de nombreuses fonctionnalités puissantes et améliorer la performance globale du kit SDK web Azure Maps. Voici certaines des principales améliorations apportées dans cette mise à jour :

  • Améliorations de l’API centrées sur les développeurs
  • Nouveau modèle de couche et de source de données
  • Connexion de plusieurs couches à une source de données
  • Nouvelle classe Shape facile à manager
  • Style de couches axé sur les données
  • Bibliothèque mathématique spatiale
  • Prise en charge de cercles corrects sur le plan géospatial

Améliorations de l’API centrées sur les développeurs

Nous avons amélioré l’interface de notre API pour la rendre plus intuitive et en améliorer les performances. Auparavant, la plupart des fonctionnalités dans le kit SDK était exposée en tant que fonctions de la classe Map. Sans le regroupement des fonctions connexes, les développeurs étaient souvent obligés d’analyser presque chaque fonction et propriété dans le kit SDK afin de trouver la fonction dont ils avaient besoin. Dans cette version, nous avons regroupé de nombreuses fonctionnalités connexes et celles-ci sont exposées via les propriétés du gestionnaire de la classe Map. Dans la dernière version, la classe Map contenait plus de 30 fonctions, dont 7 étaient liées aux couches de données. Dans cette mise à jour, ces fonctionnalités sont désormais exposées via la propriété « layers » de la carte, tout comme de nombreuses fonctionnalités supplémentaires qui facilitent l’utilisation des couches. Nous avons également ajouté des propriétés de gestionnaire à la carte pour les contrôles, les événements, le sprite d’image de carte, les marqueurs HTML et les sources de données.

Nous avons également ajouté une option permettant de définir de nombreux paramètres du kit SDK Maps par défaut directement dans l’espace de noms atlas racine du kit SDK. Par conséquent, toutes les instances de carte créées sur une page et tous les clients de service créés utiliseront les paramètres par défaut. Auparavant, les instances de carte et les clients de service ajoutés à votre application nécessitaient la transmission de votre clé Azure Maps lors de l’initialisation de cette fonctionnalité. Cela signifie que vous deviez définir ce même paramètre plusieurs fois dans votre application, ce qui peut s’avérer fastidieux. En définissant votre clé dans l’espace de noms atlas racine, il vous suffit de la spécifier une fois dans votre application, ce qui facilite la mise à jour future si nécessaire.

atlas.setSubscriptionKey('Votre clé Azure Maps');

Plusieurs autres paramètres, comme la langue et la région de l’utilisateur, peuvent également être définis comme valeurs par défaut dans l’espace de noms atlas racine. Il est important de noter qu’il s’agit là de valeurs par défaut qui seront utilisées si l’option équivalente n’est pas spécifiée lors de l’initialisation d’une instance de carte ou d’un client de service. Si, par exemple, vous transmettez une langue différente lors de l’initialisation de la carte, c’est cette langue qui sera utilisée. Cela peut s’avérer utile si vous voulez afficher plusieurs cartes sur une page dans des langues différentes.

Toutes ces améliorations axées sur les développeurs facilitent le développement d’applications avec Azure Maps, tout en augmentant les performances et en réduisant la quantité de code requis pour écrire votre application.

Nouveau modèle de couche et de source de données

Auparavant, le contrôle de carte permettait seulement d’ajouter des données spatiales de vecteur au format GeoJSON sur la carte. Ces données étaient ajoutées à une couche qui créait et gérait sa propre source de données en arrière-plan. La modification des données dans la couche nécessitait de remplacer la couche existante, ce qui n’est pas efficace et requiert du code non intuitif, comme le montre l’exemple suivant.

var myPins = [/* Matrice avec des données de repère */];

//Ajouter des repères à la carte.
map.addPins(pins, {
     name: 'MyPinLayer'
});

//Créer un nouveau repère à ajouter à la couche.
var pin = new atlas.data.Feature(new atlas.data.Point(lon, lat));

//Ajouter le repère à la matrice de repères.
myPins.push(pin);

//Mettre à jour la couche en remplaçant toutes les données qu’elle contient. Ceci n’est pas intuitif et crée un problème de performance.
map.addPins(pins, {
     name: 'MyPinLayer',  
     overwrite: true
});

Dans cette version, nous avons séparé la source des données de la couche, ce qui offre plusieurs avantages, comme la capacité d’effectuer le rendu d’une seule source de données à l’aide de plusieurs couches tout en conservant une seule instance de la source de données. Ceci permet de limiter l’utilisation de la mémoire, d’améliorer la performance et de créer une API beaucoup plus facile à comprendre, comme vous pouvez le voir ci-dessous.

//Créer une source de données et l’ajouter à la carte.
var dataSource = new atlas.source.DataSource();
map.sources.add(dataSource);

//Créer une couche qui définit comment effectuer le rendu des formes dans la source de données et l’ajouter à la carte.
var myPinLayer = new atlas.layer.SymbolLayer(dataSource);
map.layers.add(myPinLayer);

//Ajouter des repères à la source de données.
dataSource.add([/* Matrice avec des données de repère */]);

//Créer un nouveau repère à ajouter à la carte.
var pin = new atlas.data.Feature(atlas.data.Point([lon, lat]));

//Ajouter le repère à la source de données, la carte le met automatiquement à jour de la manière la plus efficace possible.
dataSource.add(pin);

En plus d’avoir la classe DataSource pour les données au format GeoJSON, nous avons aussi ajouté la prise en charge des services de mosaïque de vecteur via la nouvelle classe VectorTileSource. Ces sources de données peuvent être jointes aux couches suivantes qui définissent la façon dont les données sont rendues sur la carte.

  • Couche Bulle – Effectuer le rendu des données de point sous forme de cercles à l’échelle à l’aide d’un rayon de pixels.
  • Couche Ligne – Effectuer le rendu des lignes et des contours d’un polygone.
  • Couche Polygone – Effectuer le rendu de la zone remplie des polygones.
  • Couche Symbole – Effectuer le rendu des données de point sous forme d’icônes et de texte.

Il existe aussi une classe TileLayer qui vous permet de superposer des images en mosaïque raster sur la carte. Plutôt que de joindre cette couche à une source de données, les informations du service de mosaïque sont spécifiées en tant qu’options de la couche.

Lors de la création de cette nouvelle source de données et de ce nouveau modèle de couche dans le kit SDK, nous avons aussi plus que doublé le nombre de caractéristiques fonctionnelles et d’options de rendu pour la visualisation des données sur la carte.

Connexion de plusieurs couches à une source de données

Comme mentionné précédemment, vous pouvez désormais joindre plusieurs couches à la même source de données. Cela peut sembler étrange, mais il existe de nombreux scénarios où cela peut s’avérer utile. Prenons, par exemple, le scénario de création d’une expérience de dessin d’un polygone. Lorsqu’un utilisateur est autorisé à dessiner un polygone, nous devons effectuer le rendu de la zone de remplissage du polygone alors que l’utilisateur ajoute des points sur la carte. L’ajout d’une ligne stylisée qui dresse le contour du polygone facilite la visualisation des bords du polygone lorsque celui-ci est dessiné. Enfin, l’ajout d’une poignée, comme un repère ou un marqueur, au-dessus de chaque position du polygone facilite la modification de chaque position individuelle. Voici une image illustrant ce scénario.

Connexion de plusieurs couches à une source de données

Pour accomplir ceci dans la plupart des plateformes de mappage, vous auriez besoin de créer un objet polygone, un objet ligne et un repère pour chaque position du polygone. Lorsque le polygone est modifié, il vous faudrait mettre à jour manuellement la ligne et les repères. Le travail requis pour cela devient très rapidement complexe.

Avec Azure Maps, il vous suffit de disposer d’un seul polygone dans une source de données, comme illustré dans le code ci-dessous.

//Créer une source de données et l’ajouter à la carte.
var dataSource = new atlas.source.DataSource();
map.sources.add(dataSource);

//Créer un polygone et l’ajouter à la source de données.
dataSource.add(new atlas.data.Polygon([[[/* Coordonnées du polygone */]]]));

//Créer une couche polygone pour effectuer le rendu de la zone remplie du polygone.
var polygonLayer = new atlas.layer.PolygonLayer(dataSource, 'myPolygonLayer', {
     fillColor: 'rgba(255,165,0,0.2)'
});

//Créer une couche ligne pour un meilleur contrôle sur le rendu du contour du polygone.
var lineLayer = new atlas.layer.LineLayer(dataSource, 'myLineLayer', {
     color: 'orange',
     width: 2
});

//Créer une couche bulle pour effectuer le rendu des vertex du polygone sous forme de cercles mis à l’échelle.
var bubbleLayer = new atlas.layer.BubbleLayer(dataSource, 'myBubbleLayer', {
     color: 'orange',
     radius: 5,
     outlineColor: 'white',
     outlineWidth: 2
});

//Ajouter toutes les couches à la carte.
map.layers.add([polygonLayer, lineLayer, bubbleLayer]);

Voir des exemples en direct.

Nouvelle classe Shape facile à manager

Toutes les données basées sur un vecteur dans le kit SDK web Azure Maps consistent en des objets GeoJSON qui, en fin de compte, sont des objets JSON qui respectent un schéma défini. Une des limitations de l’utilisation de données GeoJSON est que si vous modifiez les données, la carte ne sait pas qu’il existe une modification tant que vous n’avez pas supprimé et remplacé l’objet sur la carte. Pour que le processus soit plus facile et plus intuitif, nous avons ajouté une nouvelle classe Shape qui peut encapsuler n’importe quelle fonctionnalité ou géométrie GeoJSON. Cette classe offre plusieurs fonctions qui facilitent la mise à jour des données GeoJSON et qui reflètent instantanément ces modifications dans la source de données à laquelle la classe Shape a été ajoutée. Nous avons trouvé cette fonction si utile que nous avons décidé d’encapsuler automatiquement tous les objets GeoJSON ajoutés à la classe DataSource.

Prenons, par exemple, le scénario où vous voulez mettre à jour la position d’un point de données sur la carte. Auparavant, vous deviez gérer les données dans la couche séparément, puis remplacer la couche comme illustré dans le code ci-dessous.

//Créer un repère à partir d’une fonctionnalité de point.
var pin = new atlas.data.Feature(new atlas.data.Point([-110, 45]));

//Ajouter un repère à la carte.
map.addPins([pin], {
     name: 'MyPinLayer'
});

//Mettre à jour les coordonnées des repères... La carte n’est pas mise à jour.
pin.geometry.coordinates = [-120, 30];

//Remplacer tous les repères dans la couche pour mettre la carte à jour.
map.addPins([pin], {
     name: 'MyPinLayer',
     overwrite: true
});

Cette procédure n’est pas intuitive et nécessite beaucoup trop de travail. En encapsulant le point de données avec la classe Shape, une seule ligne de code suffit pour mettre à jour la position du point de données sur la carte, comme illustré dans le code ci-dessous.

//Créer une source de données et l’ajouter à la carte.
var dataSource = new atlas.source.DataSource();
map.sources.add(dataSource);

//Créer une couche qui définit comment effectuer le rendu des formes dans la source de données et l’ajouter à la carte.
var myPinLayer = new atlas.layer.SymbolLayer(dataSource);
map.layers.add(myPinLayer);

//Créer un repère, l’encapsuler avec la classe Shape et l’ajouter à la source de données.
var pin = new atlas.Shape(new atlas.data.Point([-110, 45]));
dataSource.add(pin);

//Mettre à jour les coordonnées du repère, la carte est mise à jour automatiquement.
pin.setCoordinates([-120, 30]);

Conseil : vous pouvez facilement récupérer la version encapsulée dans la classe Shape de vos données à partir de la source de données plutôt qu’en encapsulant chaque objet individuellement.

Style de couches axé sur les données

Les capacités de style axé sur les données avec des fonctions de propriété constituent une nouvelle fonctionnalité clé de cette mise à jour. Ceci vous permet d’ajouter une logique métier à des options de style individuelles prenant en charge les propriétés définies sur chaque forme individuelle dans la source de données jointe. Le niveau de zoom peut aussi être pris en compte lors du rendu de la couche. Les styles axés sur les données peuvent réduire considérablement la quantité de code qu’il vous faudrait normalement écrire et ils définissent ce type de logique métier à l’aide d’instructions if et de la surveillance des événements de la carte.

Prenons, par exemple, les données liées à un tremblement de terre. Chaque point de données a une propriété de magnitude. Pour afficher la magnitude connexe de chaque point de données sur une carte, nous pourrions dessiner des cercles à l’échelle à l’aide de BubbleLayer où plus la magnitude d’un point de données est élevée, plus le rayon du cercle est grand. Le code suivant illustre comment appliquer un style axé sur les données à l’option du rayon dans BubbleLayer, ce qui met à l’échelle le rayon en fonction de la propriété de magnitude de chaque point de données sur une échelle linéaire débutant à 2 pixels, avec la magnitude comprise entre 0 et 40 pixels, et la magnitude étant égale à 8. 

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

Nous pouvons aussi appliquer un style axé sur les données similaire qui définit la couleur de chaque cercle et génère une carte qui ressemble à ce qui suit.

Style de carte axé sur les données

Voir un exemple en direct.

Bibliothèque mathématique spatiale

Une nouvelle bibliothèque mathématique spatiale a été ajoutée à l’espace de noms atlas.math. Elle offre une collection de calculs utiles couramment utilisés dans de nombreuses applications de mappage. Certaines des fonctionnalités permettent de calculer :

  • La distance en ligne droite entre deux positions.
  • La longueur d’une ligne ou d’un tracé.
  • La direction entre deux positions.
  • Les conversions de distance.
  • Les splines cardinaux, qui permettent de calculer les tracés courbés fluides entre un ensemble de points.
  • Les tracés géodésiques, qui correspondent au tracé direct entre deux points prenant en compte la courbure de la terre.
  • Les positions intermédiaires le long d’un tracé.

Voir un exemple en direct.

Cette bibliothèque offre de nombreux calculs spatiaux simples et courants. Si vous avez besoin de calculs spatiaux plus avancés, comme les intersections ou les unions géométriques, la bibliothèque Turf.js open source pourrait vous être utile. La bibliothèque Turf.js peut être utilisée facilement avec Azure Maps, car elle est conçue pour fonctionner directement avec les données GeoJSON qui constituent le format de base pour toutes les données de vecteur dans Azure Maps.

Prise en charge de cercles corrects sur le plan géospatial

Le schéma GeoJSON ne fournit pas une solution standard pour définir un cercle correct sur le plan géospatial. Par conséquent, l’équipe Azure Maps a normalisé une façon courante de définir un cercle correct sur le plan géospatial dans GeoJSON sans casser le schéma, comme indiqué dans notre documentation. Vous pouvez définir des objets GeoJSON à l’aide du format JSON brut dans le contrôle web Azure Maps ou à l’aide des classes de programme d’assistance dans l’espace de noms atlas.data. Voici un exemple illustrant comment définir un cercle d’un rayon de 1 000 mètres au-dessus de Seattle.

À l’aide du format JSON brut

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

À l’aide des classes de programmes d’assistance dans l’espace de noms atlas.data

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

Lors du rendu de ces cercles, le contrôle web Azure Maps convertit cette fonctionnalité Point en un polygone circulaire qui peut être utilisé avec un grand nombre de couches de rendu différentes. Voici une carte où le cercle est rendu sous forme de polygone rempli.

Carte de Seattle

Voir un exemple en direct.

Une des différences principales entre les cercles corrects sur le plan géospatial et les cercles générés par BubbleLayer est que la couche Bulle assigne un rayon de pixels pour chaque bulle. Lorsque l’utilisateur effectue un zoom avant sur la carte, le rayon de pixels ne change pas, mais la zone de la carte couverte par la bulle change. Dans le cas d’un cercle correct sur le plan géospatial, ses vertex sont liés à des coordonnées sur la carte. Lors d’un zoom avant sur la carte, le cercle se met à l’échelle et conserve la zone qu’il couvre.

Il est important de noter que ces cercles peuvent ne pas toujours apparaître comme circulaires en raison de la projection Mercator utilisée par la carte. En fait, plus le cercle est proche du Pôle Nord ou du Pôle Sud, plus il peut apparaître grand et elliptique. Toutefois, la zone qu’il représente sur un globe est circulaire. La carte suivante illustre deux cercles avec un rayon de 750 Km (750 000 mètres). Un cercle couvre le Groenland, qui est proche du Pôle Nord, tandis que l’autre cercle couvre le Brésil, qui est proche de l’Équateur.

Exemple Azure Maps Geocircle

Voir un exemple en direct.

Compatibilité descendante

Si vous avez déjà développé une application avec Azure Maps, vous vous demandez peut-être si cela signifie que vous devez réécrire toute votre application. La réponse est non. Nous avons travaillé dur pour maintenir la compatibilité descendante. De nombreuses anciennes fonctions ont été marquées comme étant déconseillées dans notre documentation afin d’empêcher les développeurs de les utiliser dans de futures applications. Mais ces fonctionnalités seront toujours prises en charge comme dans la version 1 du kit SDK.

Cela étant, nous avons découvert quelques applications ayant ignoré une étape importante lors de l’utilisation du contrôle de carte. Quand une instance du contrôle de carte est créée, elle doit charger plusieurs ressources, comme le canevas Web-GL. Cela se produit relativement vite, mais de manière asynchrone, ce qui signifie que la ligne suivante de code après la création de l’instance de carte peut potentiellement être appelée avant que le chargement de la carte ne soit terminé. Si cette ligne de code tente d’interagir avec la carte avant que celle-ci ne soit chargée, une erreur peut se produire. Pour résoudre ce problème, l’événement « load » doit être joint à la carte et la fonctionnalité qui doit s’exécuter une fois la carte chargée doit être ajoutée dans le rappel de l’événement. Si vous n’utilisez pas actuellement l’événement de chargement de la carte, votre application peut fonctionner correctement la plupart du temps, mais cela peut ne pas être le cas sur l’appareil d’un autre utilisateur. Voici du code qui illustre le problème et la manière de le résoudre.

Problème

//Initialiser une instance de carte.
var map = new atlas.Map('myMap', {
     'subscription-key': 'Your Azure Maps Key'
});

//Code supplémentaire qui interagit avec la carte. Le chargement de la carte n’est peut-être pas encore terminé.

Résolution à l’aide de l’interface d’une API plus ancienne (toujours prise en charge)

//Initialiser une instance de carte.
var map = new atlas.Map('myMap', {
     'subscription-key': 'Your Azure Maps Key'
});

//Attendez que les ressources de la carte aient été entièrement chargées.
map.addEventListener("load", function (e) {
     //Add your additional code that interacts with the map here.
});

Résolution à l’aide de l’interface de la nouvelle API

//Ajouter votre clé d’abonnement Azure Maps au kit SDK de la carte.
atlas.setSubscriptionKey('Votre clé Azure Maps');

//Initialiser une instance de carte.
var map = new atlas.Map('myMap');

//Attendez que les ressources de la carte aient été entièrement chargées.
map.events.add('load', function (e) {
     //Add your additional code that interacts with the map here.
});

Nous sommes à votre écoute.

Nous travaillons toujours en vue de développer et d’améliorer la plateforme Azure Maps et nous souhaitons obtenir votre avis.

  • Vous avez une suggestion concernant une fonctionnalité ? Ajoutez-la ou votez pour une requête existante sur notre site dédié aux commentaires.
  • Vous avez trouvé un problème dans les données de la carte ? Signalez-le directement à notre fournisseur de données avec l’outil Map Share Reporter de TomTom.
  • Votre code vous pose un problème ? Existe-t-il un sujet que vous aimeriez que nous traitions sur le blog Azure ? Posez-nous une question sur les forums Azure Maps. Nous sommes là pour vous aider et nous voulons que vous profitiez au mieux de la plateforme Azure Maps.
  • Vous recherchez des exemples de code ou vous avez écrit un excellent code que vous aimeriez partager ? Rejoignez-nous sur GitHub.