Ajout de l’interactivité
Les interactivités seront les mêmes :
- Surlignage d’une ligne au survol de la souris
- Agrandissement d’un marqueur de station au survol de la souris
- Affichage d’informations dans un encart
Ajout de l’encart
L’encart est rajouté directement dans le code HTML, en l’ajoutant dans une div qui englobe également celle de la carte :
<div id="map-wrap">
<div id="map"></div>
<div id="info"></div>
</div>
La mise à jour de l’encart est faite dans une fonction attachée à l’événement « pointermove » sur la carte.
Interactivité sur les éléments
L’interactivité des éléments est gérée par la même fonction que celle qui met à jour l’encart d’information.
Mais cette fonction gère autre chose que l’affichage des informations de l’élément survolée, c’est aussi elle qui doit gérer le z-index des différents éléments de chaque calque.
Les lignes
Pour que les lignes aient le même comportement qu’avec Leaflet (la ligne sélectionnée se positionne au-dessus de toutes les autres et y reste) il faut utiliser un array qui contiendra les z-index de chaque ligne. Et ce z-index est mis à jour à chaque survol de souris de la ligne.
On a également besoin d’une variable pour contenir la ligne actuellement survolée.
Les stations
Pour les stations, on a besoin de deux variables : une pour contenir la station actuellement survolée, l’autre pour contenir la dernière station survolée.
Le code
Notre code devient donc (l’initialisation de la carte étant la même, je ne la mets pas ci-dessous pour des questions de lisibilité) :
var info = document.getElementById('info'); // on récupère l’encart d’info
info.innerHTML = '<p>Survoler un élément</p>'; // on l’initialise
var curLine = ''; // pour contenir la ligne actuellement survolée
var curStop = ''; // pour contenir la station actuellement survolée
var lastStop = ''; // pour contenir la dernière station survolée
var zIndexes = {}; // tableau des différents z-index
var zIndexCount = 0; // z-index à attribuer
var firstDraw = true; // flag pour indiquer si il y a besoin de remplir le tableau des z-index
var lines = new ol.layer.Vector({
source: new ol.source.Vector({
features: (new ol.format.GeoJSON({featureProjection:'EPSG:3857'})).readFeatures(metro_lines)
}),
style: function(feature) {
var key = feature.get('line');
if (firstDraw) { // si besoin, on créé le z-index pour la feature
zIndexes[key] = zIndexCount;
zIndexCount++;
}
return new ol.style.Style({
stroke: new ol.style.Stroke({
width: curLine == key ? 6 : 4, // si c’est la feature actuellement survolée, la largeur doit être plus grande
color: feature.get('color')
}),
zIndex: zIndexes[key]
});
}
});
map.addLayer(lines);
var stops = new ol.layer.Vector({
source: new ol.source.Vector({
features: (new ol.format.GeoJSON({featureProjection:'EPSG:3857'})).readFeatures(metro_stations)
}),
style: function(feature) {
var key = feature.get('name') + '' + feature.get('about');
return new ol.style.Style({
image: new ol.style.Icon({
src: './symbole.1541586932.svg',
scale: curStop == key ? 0.2 : 0.15 // si c’est la feature actuellement survolée, le marqueur doit être plus grand
}),
zIndex: (curStop == key || lastStop == key) ? 650 : 500 // si c’est la feature survoléé, ou la dernière survolée, le z-index doit être plus élevé
});
}
});
map.addLayer(stops);
map.on('pointermove', function(evt){ // appelée à chaque mouvement de souris sur la carte
if (evt.dragging) return;
if (firstDraw) firstDraw = false; // au premier appel, la carte étant déjà rendue, il n’y a plus besoin de remplir le tableau des z-index
var feature = map.forEachFeatureAtPixel(evt.pixel, function(feature) { // permet de détecter si il y a une feature sous la souris
return feature;
});
if(feature){
if(feature.get('line')) {
curLine = feature.get('line');
lastLine = '';
// mise à jour du z-index de la feature
zIndexCount++;
zIndexes[curLine] = zIndexCount;
info.innerHTML = '<p>Ligne ' + feature.get('line') + '</p>';
resetStop();
} else {
curStop = feature.get('name') + '' + feature.get('about');
lastStop = '';
info.innerHTML = '<p>' + feature.get('name') + ' – ' + feature.get('about') + '</p>';
resetLine();
}
} else {
resetLine();
resetStop();
info.innerHTML = '<p>Survoler un élément</p>';
}
// on redessine les calques en relançant leur propre fonction
lines.setStyle(lines.getStyle());
stops.setStyle(stops.getStyle());
});
function resetLine() {
if(curLine != ''){
curLine = '';
}
}
function resetStop() {
if(curStop != ''){
lastStop = curStop;
curStop = '';
}
}
La version finale de cette carte est disponible sur mon site : Carte interactive du métro de Paris avec OpenLayers.