Carte interactive du métro de Paris avec OpenLayers

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.

Laisser un commentaire