Skip to content

[OpenLayers] Utiliser les outils liés au contrôle OL.Control.SelectFeature

Dans le cadre d’un projet personnel mêlant développement web et cartographie, dont je reparlerais probablement bientôt sur ce blog, j’ai remis les mains dans la librairie OpenLayers. Pour les besoins du projet, j’ai du pas mal travailler avec les fonctionnalités liées à la sélection d’entités. Comme j’ai parfois galéré avec certaines des propriétés et des méthodes concernées, j’ai fait ici une petite synthèse de ce qu’un projet de base pourrait avoir besoin. Je m’excuse par avance : il n’y aura pas d’image dans cet article quelque peu indigeste…

Paramétrer le contrôle de sélection lors de la création de la carte

La mise en place du contrôle de sélection s’opère, dans votre code source, après la création de la carte et après l’ajout de la couche qui va être concernée par ce contrôle de sélection, bien évidemment.

var controleSelection = new OpenLayers.Control.SelectFeature(maCouche,{hover:false,multiple:false,box:false,onSelect:selectionnerEntite,onUnselect:deselectionnerEntite});
cartographie.addControl(controleSelection);
controleSelection.activate();

La création et le paramétrage du contrôle se fait donc en trois temps ici : création du contrôle (avec les options désirées), ajout du contrôle à l’objet « carte » et activation du contrôle. Parmi les options disponibles pour configurer votre contrôle, je vais détailler celles qui me paraissent incontournables :

– hover (« true » ou « false ») : si cette propriété vaut true, la sélection d’une entité se fait en la survolant; si elle vaut false, la sélection se fera en cliquant.

– multiple (« true » ou « false ») : si cette propriété vaut true, vous pourrez sélectionner plusieurs entités en même temps; si elle vaut false, la sélection d’une entité déclenchera systématiquement la déselection de l’entité éventuellement déjà sélectionnée.

– box (« true » ou « false ») : si cette propriété vaut true, la sélection d’une ou plusieurs entités peut se faire en dessinant un rectangle d’emprise sur la carte (nécessite l’activation d’autres contrôles).

– onSelect : vous pouvez indiquer la fonction ou le nom de la fonction (sans les parenthèses) que vous désirez appeler lorsqu’une entité sera sélectionnée (normalement ou manuellement). Nous verrons cela quelques paragraphes plus bas…

– onUnselect : ici, mêmes indications que pour la propriété précédente, mais, cette fois, dans le cas d’une déselection (normale ou manuelle).

Proposer deux sémiologies différentes (aspect normal / aspect sélectionné)

Je ne vais pas ici détailler toutes les options disponibles à votre disposition pour configurer vos sémiologies et vos étiquettes. Sachez juste que vous pouvez définir deux styles différents : un pour l’aspect normal de vos figurés et un second pour l’aspect « sélectionné ». Pour ce dernier style, ne prenez pas la peine de tout répéter : n’indiquez que ce qui change, comme la couleur de remplissage (fillColor) dans cet exemple :

var defaultStyle = new OpenLayers.Style({pointRadius:4,strokeWidth:1,fillColor:'#edb759',strokeColor:'black',cursor:'pointer'});
var selectStyle = new OpenLayers.Style({fillColor:'#36b7d1');
var styleMap = new OpenLayers.StyleMap({'default':defaultStyle,'select':selectStyle});
var maCouche = new OpenLayers.Layer.Vector('Ma couche exemple',{styleMap:styleMap});

Le bout de code ci-dessus définit donc deux styles. L’un est affecté à l’état ‘default’ et l’autre à l’état ‘select’. Evidemment, d’autres états existent mais on ne s’intéresse qu’à ceux-là ici. Les deux styles sont donc intégrés à une « styleMap », qui est ensuite elle-même associée à notre couche. OpenLayers s’occupera d’appliquer ces différents styles selon les sélections qui seront faites sur la carte.

Faire une action à la sélection/déselection d’une entité

Comme nous l’avons rapidement vu plus haut, il est possible d’indiquer à OpenLayers des fonctions qu’il devra appeler lors de la sélection (onSelect) et de la déselection (onUnselect) d’une entité :

var controleSelection = new OpenLayers.Control.SelectFeature(maCouche,{hover:false,multiple:false,box:false,onSelect:selectionnerEntite,onUnselect:deselectionnerEntite});

La chose intéressante, c’est qu’OpenLayers appellera ces fonctions en passant l’entité (OpenLayers.Feature.Vector) sélectionnée (ou déselectionnée) en argument. Ainsi, vous aurez accès directement aux propriétés de l’entité (géométrie et attributs). Dans l’exemple suivant, juste après la sélection, on va écrire la fonction qui sera appelée. Elle aura pour but de centrer la carte sur le centroïde de l’entité sélectionnée, puis on va afficher la valeur d’un de ses attributs.

function selectionnerEntite(feature)
{
	cartographie.panTo(feature.geometry.getBounds().getCenterLonLat());
	alert('Mon attribut monChamp vaut ' + feature.attributes['monChamp']);
}

Parcourir les entités sélectionnées actuellement

A tout moment, vous avez accès à un array composé de toutes les entités actuellement sélectionnées d’une couche donnée, avec sa propriété selectedFeatures.

var entites_selectionnees = maCouche.selectedFeatures;

Il ne vous reste plus qu’à le parcourir (avec une boucle for par exemple) et imaginer ce que vous pouvez faire avec chacune des entités (OpenLayers.Feature.Vector) qui composent l’array.

Déclencher une sélection manuellement

Pour ce faire, il vous faudra utiliser la fonction select(), qui prend une entité (OpenLayers.Feature.Vector) en argument.

controleSelection.select(feature);

La question qu’il reste à résoudre, c’est comment isoler l’entité qui nous intéresse, parmi toutes les entités de la couche. Pour cela, vous avez plusieurs fonctions à votre disposition : getFeatureFromEvent(), getFeatureBy(), getFeatureById(), getFeatureByFid() et getFeaturesByAttribute().

Cette dernière méthode est particulièrement intéressante, puisqu’elle permet de récupérer toutes les entités pour lesquelles un champ vaut une valeur :

var features = maCouche.getFeaturesByAttribute('monChamp','maValeur');

Attention, cette fonction renvoie un array composé d’une ou plusieurs entités (OpenLayers.Feature.Vector). Si plusieurs entités correspondent à ce que vous avez demandé, il vous faudra parcourir cet array (via une boucle for par exemple). A l’inverse, si vos valeurs sont « uniques », vous pouvez vous contenter du bout de code suivant (utilisation du premier et seul élément de l’array) :

var features = maCouche.getFeaturesByAttribute('monChamp','maValeur');
controleSelection.select(features[0]);

En appellant cette fonction select(), OpenLayers se chargera tout seul d’ajouter l’entité à l’array des entités sélectionnés actuellement (maCouche.selectedFeatures), redessiner l’entité si un style particulier a été défini en amont pour ce qui est sélectionné, et d’appeler la fonction indiquée dans la propriété « onSelect » du contrôle.

Déclencher une déselection manuellement

Vous avez la possibilité de déselectionner tout ce qui est sélectionné actuellement, grâce à la fonction unselectAll(), qui s’appelle sur le contrôle de sélection et qui ne prend aucun argument.

controleSelection.unselectAll();

A noter qu’il existe aussi une fonction unselect(), qui prend une entité (OpenLayers.Feature.Vector) en argument, pour ne déselectionner que celle-là.

controleSelection.unselect(feature);

En appellant ces deux fonctions, OpenLayers se chargera tout seul de retirer l’entité de l’array des entités sélectionnés actuellement (maCouche.selectedFeatures), redessiner l’entité selon le style « normal » défini en amont, et d’appeler la fonction indiquée dans la propriété « onUnselect » du contrôle.

Démonstration

http://labs.adrienvh.fr/blog/ol_control_selectfeature/

  1. Marc F. Permalien

    Merci pour cet article fort éclairant sur ces aspects d’OpenLayer.
    Ce sera très vite mis à profit pour une appli du domaine transport public: chouette.mobi

    Commentaire déposé le 17/08/2012
    • Ravi d’avoir été utile :) Si vous avez des questions ou des remarques, n’hésitez surtout pas…

      Commentaire déposé le 17/08/2012
  2. Chaima Permalien

    This was helpful indeed, Merci infiniment!

    Commentaire déposé le 28/03/2015
  3. compilator Permalien

    Je travaille sur un projet carto avec notre bien aimé OpenLayers et je rencontre quelques difficultés.

    Pourrez-vous svp m’apporter des bouts de codes qui puissent m’aider à gérer la légende de la carte et à l’imprimer ???

    j’en serais vraiment reconnaissant.

    Merci d’avance.
    Cordialement.
    IT ENGINEER

    Commentaire déposé le 08/05/2015

Répondre à Chaima Annuler la réponse.

Vous pouvez utiliser un peu d'HTML dans votre commentaire.
Votre adresse e-mail ne sera pas publiée.

S'inscrire au flux RSS des commentaires de ce billet