Rechercher dans le blog

Changez la symbologie d'une couche de votre carte web avec les Web Style Symbols 3D

Après avoir créé une carte web puis y avoir ajouté une couche issue d'un fichier GeoJSON grâce à l'API JavaScript d'ArcGIS, nous allons continuer notre série de tutoriels en modifiant la manière dont la couche s'affiche en travaillant sur sa symbologie.
Voici le résultat que nous obtiendrons à la fin de cette étape :
Nous allons remplacer les points représentant les arbres remarquables par des modèles 3D correspondant à l'espèce de l'arbre, et retirer temporairement les arbres présents par défaut sur le fond de carte utilisé. Comme les semaines précédentes, vous pouvez suivre le tutoriel ci-dessous pour obtenir ce résultat, ou  bien vous rendre sur ce CodePen pour tester directement le comportement du code.

Utiliser des styles de symboles web (web style symbols) pour le rendu d'une couche

Pour personnaliser le rendu d'une couche avec l'API, il va falloir paramétrer le symbole sur lequel s'appuie le rendu. Plusieurs options s'offrent à vous : vous pouvez configurer vos symboles ponctuels, linéaires, surfaciques ou 3D vous-même, utiliser des CIMSymbols très personnalisables ou, comme nous allons le faire ici, utiliser des WebStyleSymbols.
Les WebStyleSymbols sont une collection de symboles thématiques, 2D et 3D, mis à disposition par Esri. Lors de la dernière mise à jour de l'API JavaScript d'ArcGIS en version 4.27, la collection de styles de symboles web 3D s'est étoffée avec la mise à disposition du style Low Poly Vegetation, représentant différents types d'arbres dans un style low poly.
Nous allons utiliser ce tout nouveau style pour représenter les arbres remarquables. En cliquant sur n'importe lequel des symboles de cette collection, l'aide en ligne nous renseigne sur la configuration de ses paramètres :
Un webStyleSymbol est défini par le nom du style auquel il appartient (styleName) et son nom propre (name). Pour tous les symboles de cette collection, le styleName sera systématiquement "EsriLowPolyVegetationStyle". Les noms quand à eux seront différents pour chaque arbre, et à aller chercher dans la documentation.
La page de l'aide en ligne dédiée aux WebStyleSymbols nous renseigne sur les propriétés utilisables pour les configurer. En plus de la propriété name et styleName, nous devons renseigner la propriété type, dont la valeur est toujours "web-style" pour les symboles de la classe WebStyleSymbol.
En résumé, nous avons besoin d'une vingtaine de symboles de type web style pour chacun des types d'arbres à afficher, et chacun d'entre eux est défini par trois propriétés dont deux seront toujours identiques : seul le nom changera d'un arbre à l'autre. Afin d'alléger notre code, nous allons écrire une fonction qui prend en paramètre le nom de l'arbre (que nous trouverons à chaque fois dans la documentation), et qui retourne l'ensemble des trois paramètres :
/*fonction pour retrouver les WebStyleSymbols du style low poly vegetation 
en se basant sur le nom de l'arbre*/
function getTreeSymbol(name) {
    return {
        type: "web-style",
        name: name,
        styleName: "EsriLowPolyVegetationStyle"
    };
}
Vous pouvez ajouter cette fonction dans votre code au-dessus de l'instance GeoJSONLayer créée la semaine dernière.
Nous pourrons ensuite appeler cette fonction pour chacun des arbres dans l'étape suivante. A titre d'exemple, pour le cocotier montré juste au-dessus, voici comment appeler la fonction :  
getTreeSymbol("Cocos")

Faire une symbologie par valeurs unique

Il existe de nombreuses manières de représenter les données :  des rendus simples, où toutes les entités sont représentées avec le même symbole ; des rendus par classes se basant sur des classes ou des plages de données numériques ; des rendus par densité de points, par carte de chaleur, etc. 
Aujourd'hui, nous nous intéressons au rendu par valeurs uniques, qui nous permettent de définir un symbole pour chaque catégorie de données, qui seront donc ici chacun des types d'arbres présents dans notre couche.
Voici comment construire notre rendu (renderer) par valeurs uniques :
const treeRenderer = {
  type: "unique-value", // autocasts as new UniqueValueRenderer()
  field: "arbres_libellefrancais",
  defaultSymbol: getTreeSymbol("Chilopsis"),
  uniqueValueInfos: [
            {
              value: "Aulne",
              symbol: getTreeSymbol("Frangula")
            },
            {
              value: "Bouleau",
              symbol: getTreeSymbol("Betula")
            },
            {
              value: "Cèdre",
              symbol: getTreeSymbol("Calocedrus")
            },
            {
              value: "Chêne",
              symbol: getTreeSymbol("Quercus Rubra")
            },
            //ajouter tous les types d'arbres
  ],
}; 
Nous devons dans un premier temps renseigner le type de rendu que nous voulons utiliser, ici de type "unique-value" pour valeurs uniques. 
Ensuite, nous devons signaler dans la propriété field sur quel champ de la donnée nous nous basons pour définir les catégories, c'est-à-dire ici quelle colonne de la table attributaire contient les informations nous permettant d'identifier les différents types d'arbre. Pour cette donnée, ces informations sont contenues dans un champ nommé "arbres_libellefrancais".
Il est ensuite intéressant d'utiliser la propriété defaultSymbol afin de définir quel symbole sera utilisé par défaut, lorsque l'arbre ne rentrera dans aucune des catégories que nous aurons définies à la main (cela nous sera par exemple utile pour les arbres peu représentés dans la donnée d'origine, ou pour ceux pour lesquelles la bibliothèque de symboles 3D ne met pas à disposition de modèle 3D correspondant). Pour le paramétrer, nous utilisons la fonction définie juste avant afin de faire appel à un WebStyleSymbol. L'arbre que j'ai choisi par défaut est le Chilopsis, mais vous pouvez choisir celui de votre choix.
Enfin, le paramètre structurant du rendu par valeurs unique est uniqueValueInfos, qui définit les catégories et leurs symboles associés. Il se configure avec une liste qui, pour chaque catégorie, indique la valeur de la catégorie (c'est-à-dire le nom exact que l'on retrouvera dans la table attributaire de la donnée) et le symbole qui lui est associé. A nouveau, j'utilise la fonction définie plus tôt pour faire appel aux différent WebStyleSymbols. Pour compléter le code, vous pouvez vous rendre sur Github pour récupérer la configuration complète des valeurs uniques.

Ajouter une variable visuelle

La donnée contient un autre champ très intéressant,  "arbres_hauteurenm", qui contient la hauteur en mètre de chacun des arbres remarquables de la couche. Nous allons pouvoir nous servir de ce champ pour modifier la taille du symbole qui représente individuellement chacun des arbres, et ainsi que les arbres soient représentés dans notre carte proportionellement à leur taille réelle.
Différents types de rendus, dont le rendu par valeurs uniques, nous permettent d'utiliser des variables visuelles, qui peuvent faire varier la couleur, l'opacité, l'orientation ou la taille d'un symbole en se basant sur des informations contenues dans la table attributaire de la couche.
Toujours dans l'instance treeRenderer créée juste au-dessus, nous allons configurer la propriété visualVariables du rendu. Notez que cette propriété prend en entrée une liste, et que vous pouvez donc configurer plusieurs variables visuelles de plusieurs types pour un même rendu (par exemple : hauteur et largeur ; largeur, couleur et opacité, ...).
Utilisons ici une variable visuelle jouant sur la taille (SizeVariable) :
visualVariables: [
   {
     type: "size",
     field: "arbres_hauteurenm",
     axis: "height",
     valueUnit : "meters"
    }
]
Nous indiquons son type, ici "size" pour une variable agissant sur la taille des symboles. La modification de taille peut se faire sur différents axes (axis) : hauteur, largeur, profondeur ; nous voulons ici que la hauteur (height) soit impactée. Nous renseignons également dans quel champ (field) de la table attributaire la code trouvera la taille de chacun des arbres, ainsi que l'unité (valueUnit) dans laquelle elle est exprimée.
Vous pouvez voir la différence entre le rendu avant l'ajout de la variable visuelle (à gauche), où la taille des arbres était rendue selon la taille par défaut du style de symbole web correspondant à l'arbre, et après (à droite) où la taille de l'arbre dans l'application est proportionnelle à la taille de l’arbre dans la réalité. Pour l'instant dans votre propre application, vous ne voyez pas encore la symbologie s'appliquer ; c'est parce que nous devons prévenir la couche qu'elle doit se baser sur l'instance de rendu que nous venons de définir. Nous allons voir tout de suite comment faire.

Appliquer la symbologie à la couche

Maintenant que nous avons fini de paramétrer le rendu, il est temps de l'appliquer à la couche afin qu'elle s'affiche de la manière souhaitée. En accédant à la propriété renderer de la couche créée lors du dernier tutoriel, nous pouvons indiquer à la couche d'utiliser le rendu que nous venons de paramétrer pour s'afficher. Nous allons également paramétrer la propriété elevationInfo, qui régit comment les objets se placent selon l'axe Z dans une scène 3D. Ici, nous souhaitons que nos arbres s'affichent à la surface du sol ("on-the-ground").
const arbresRemarquables = new GeoJSONLayer({
   url: "https://raw.githubusercontent.com/JapaLenos/JS-API/main/Jardins-Parisiens/app/arbresremarquablesparis.geojson",
   copyright: "Arbres remarquables - Open portail Paris Data",
   renderer: treeRenderer,
   elevationInfo: {
       mode: "on-the-ground"
   }
});
Maintenant que cette étape est effectuée, vous devriez voir apparaître dans votre application les points oranges issus de la couche GeoJSON adopter la symbologie d'arbres low poly.

Accéder à une couche de la basemap et la rendre invisible

Pour ma part, je trouve que les autres arbres 3D présents sur la carte par défaut font perdre un peu en lisibilité aux arbres remarquables. Nous allons les retirer temporairement en rendant la couche qui les contient invisible, avant de voir dans la suite de cette série durant les semaines à venir comment mettre en place un bouton qui permettra à l'utilisateur de choisir lui même d'afficher ou non la couche.
Nous allons définir chercher dans les couches de la basemap la couche contenant les arbres, en se basant sur l'identifiant de la couche. 
Pour information, une Basemap se compose généralement de deux types de couches : les baseLayers, une collection couches tuilées qui constituent les caractéristiques du fond de carte, et les referenceLayers, une collection de couches  affichées au dessus des fonds de carte et utilisés pour afficher des labels ou des objets 3D par exemple. Nous recherchons donc ici parmi les referenceLayers du fond de carte.


Pour connaître l'identifiant de la couche, j'utilise la fonction suivante :
console.log(map.basemap.referenceLayers.items);
Puis je me rends dans la console de l'inspecteur de mon navigateur pour inspecter manuellement les identifiants et retrouver le bon.

Une fois que la couche est retrouvée, nous pouvons accéder à sa propriété visible et la définir sur "false" pour que  la couche ne s'affiche pas.
Voici le code complet de cette dernière manipulation : 
//rendre les autres arbres invisibles :
let treeLayer = map.basemap.referenceLayers.find(function(layer){
   return layer.id === "1872932aeb4-layer-48";
);
treeLayer.visible = false ;
C'est tout pour aujourd'hui! Vous pouvez retrouver le code complet compilant cette étape et les précédentes sur Github ou sur CodePen. Nous nous retrouvons la semaine prochaine pour voir comment configurer des popups afin de donner plus de renseignements sur nos arbres. N'hésitez pas à retrouver les autres épisodes de cette série si vous les avez manqués.

Aucun commentaire:

Enregistrer un commentaire