Rechercher dans le blog

Interagissez intelligemment avec vos cartes Web grâce à la méthode watch()


Dans cet article, nous allons appliquer plusieurs concepts que nous avons vus précédemment pour un besoin spécifique. Nous allons importer depuis ArcGIS Online une FeatureLayer contenant les polygones des régions de France. On souhaite que notre application permette de choisir la basemap via un widget, et que, en fonction de la basemap choisie, la couche de polygone devienne transparente si celle-ci est une image satellite, sinon qu’elle reste opaque.

Widget BasemapGallery

Le widget BasemapGallery affiche une collection d'images représentant les fonds de carte d'ArcGIS.com, ou un ensemble de services de carte ou d'image définis par l'utilisateur. Lorsqu'un nouveau fond de carte est sélectionné dans BasemapGallery, il remplace le fond de carte actif. Par défaut, le widget BasemapGallery ressemble à l'image suivante :
Pour instancier le widget, il suffit de lui donner une vue à laquelle il doit être ajouté.
var basemapGallery = new BasemapGallery({
 view: view,
});

Widget Expand

Le widget Expand agit comme un bouton cliquable pour ouvrir un autre widget. Il est utile lorsqu’on a ponctuellement besoin d’un widget mais que l’on ne souhaite pas que celui-ci nous cache une grande partie de l’UI. Il suffit alors de cliquer sur l'icône du widget pour afficher le contenu à l'intérieur du widget Expand (dans ce cas, le widget BasemapGallery). Vous pouvez ensuite simplement réduire le contenu dans le widget en cliquant sur l'icône de réduction.
Lors de la création d'une instance de widget Expand, vous devez également définir la vue référencée par le widget, et le widget qu'il contiendra, ici la gallerie de basemaps.
var widgetExpand = new Expand({
 view: view,
 content: basemapGallery
});
On ajoute le widget à l’UI en haut à droite comme on l’a vu dans le précédent article.

view.ui.add(widgetExpand, "top-right");

Propriété watch et événement pour fermer le widget

La méthode watch permet de surveiller les changements de propriété d’une instance et d’agir en conséquence. Surveiller les changements de propriété est essentiel pour suivre les modifications sur les objets. Il suffit d’appeler la méthode watch () avec le nom de la propriété (de l’objet sur lequel watch est appliquée) et une fonction callback à exécuter à chaque changement de propriété : watch(property, callback)

La fonction callback est elle-même de type WatchCallback. Cela signifie d’après la documentation que la fonction callback peut prendre en argument la valeur issue du changement de la propriété de l’objet surveillée et l’ancienne valeur. Ici pas besoin, à n’importe quelle valeur de la propriété, on agit.
Au lieu d’écouter les événements pour savoir quand des modifications ont été apportées à un objet, on va pouvoir simplement surveiller les modifications sur les propriétés elles-mêmes, grâce aux accesseurs.

La méthode watch() retourne un objet watchHandle. Lorsque l’on applique la méthode watch à un objet, on peut donc stocker le résultat dans une variable. On peut alors appliquer une méthode spécifique à cet objet watchHandle, la méthode remove(), pour stopper la surveillance de la propriété de l’objet en question.
Lorsque l’on sélectionne un fond d’imagerie, je souhaite ici que ma couche de polygones devienne transparente, et que seuls les contours soient visibles pour que je puisse voir l’image en dessous. La couche de polygones est d’abord opaque.

Pour cela, je vais utiliser la méthode watch() et surveiller le changement de propriété du titre du fond de carte. Nous allons faire 2 choses :
-          Dans un premier temps, lorsque le nom de la basemap change, cela signifie qu’on a choisi une nouvelle basemap dans le widget, on va alors fermer ce widget.
-          La deuxième chose que l’on souhaite faire, c’est appliquer la transparence lorsque le fond de carte sélectionné est un fond de carte d’imagerie. 
    
     On accède à la propriété du nom du fond de carte avec view.map.basemap.title. Sachant que la méthode watch() va s’appliquer sur l’objet view on a alors simplement :
view.watch("map.basemap.title",function(){
 widgetExpand.collapse(); //fermeture du widget Expand dès qu’une basemap est sélectionnée.
// changement de symbologie quand couche d’imagerie.
})
Pour fermer le widget, la classe Expand permet d’appliquer la méthode collapse() à l’instance widgetExpand que nous avons créée, pour fermer le widget.

Changement de symbologie pour rendre les polygones transparents

On ne veut appliquer la transparence que si le fond de carte sélectionné dans le widget basemapGallery() est une imagerie. Il y a plusieurs manières de procéder. Ici, nous allons utiliser la méthode toJSON() qui s’applique à un fond de carte. Cette méthode retourne un objet JSON contenant des informations sur la basemap. Stockons-le dans une variable.
Regardons ensuite ce que nous donne le JSON dans la console à l’aide de maj+ctrl+I à l’aide d’un console.log(varJSON) dans la fonction déclenchée par le watch.


En le parcourant, dans la console, on remarque une propriété qui peut nous intéresser dans baseMapLayers[0] qui est la propriété title. Quand on regarde le fond de carte « Imagerie » et « Imagery Hybrid » dans le widget, ce title reste le même : « World Imagery ». En revanche pour les autres fonds de carte, la propriété change comme par exemple « World Street Map ». On va donc se baser sur cette propriété pour procéder à la transparence.
let varJSON=map.basemap.toJSON();
if (varJSON.baseMapLayers[0].title=="World Imagery"){
//appliquer la transparence
}
else{
//rester normal ou revenir comme avant (il a pu y avoir un passage par la transparence)
}
 
Pour appliquer la transparence, je change directement la propriété renderer de la couche. Pour éditer la capacité de remplissage d’un polygone, je choisis le type « simple » qui permet l’autocasting de la symbologie comme un nouveau SimpleRender() puis je change la propriété de symbol en simple-fill pour autocasts as new SimpleFillSymbol(), j’applique une transparence dans la propriété color.

view.watch("map.basemap.title",function(){
          widgetExpand.collapse();          
Layer.renderer = {
type: "simple",
   symbol: {
  type: "simple-fill",  // autocasts as new SimpleFillSymbol()
  color: [ 51,51, 204, 0.4 ], //last number is the opacity rate
  style: "solid",
  outline: {  // autocasts as new SimpleLineSymbol()
    color: "white",
    width:1
  }
   }
};
Comme d’habitude retrouvez tout le code sur mon Github.
Pour voir directement à quoi ressemble l'application, vous pouvez cliquer ici.

Aucun commentaire:

Enregistrer un commentaire