Une heatmap dynamique en JavaScript/HTML5
L'analyse spatiale passe par l'usage d'outils plus ou moins
complexes, mais le premier outil que nous utilisons sans même nous en rendre
compte est l’œil. La lecture d'une carte donne instantanément des
renseignements tels que : la localisation d'une infrastructure ou d'un
évènement, la répartition spatiale de ces évènements, leur nature, etc... La
vitesse de cette analyse dépend en grande partie de la représentation
cartographique choisie.
Lorsque vous affichez des couches de points sur une carte et
diffusez cette carte sur le web, se pose donc la question du mode de
représentation.
Pour un volume de données réduit et une répartition spatiale
peu dense, une bonne sélection du symbole, de sa taille et de la plage de
visibilité de la couche permettront d'assurer une bonne lisibilité de la carte.
En revanche lorsque le volume de donnée (nombre de points)
augmente ou que leur répartition spatiale est dense la carte devient illisible
et difficilement exploitable à l'œil.
Afin d'optimiser l'affichage d'une couche ponctuelles
volumineuse, deux types de symbologie s'offrent à nous:
- la symbologie sous forme d'agrégat (clustering), déjà disponible dans les API Web d'ArcGIS for Server (Silverlight, Flex, JavaScript).
- la représentation de type carte de densité (ou carte de points chauds) (heatmap).
C'est cette dernière qui nous intéresse aujourd'hui.
Qu'est-ce qu'une heatmap?
De manière générale une heatmap est une représentation
graphique des données employant des couleurs pour indiquer le degré d'activité
ou la fréquence d'apparition de la donnée, en générale des couleurs froides pur indiquer une faible densité et plus chaudes pour
indiquer une densité forte.
Les heatmap sont utilisées dans différents domaines comme
par exemple l'ergonomie et le web marketing il pour étudier le temps et les
zones de fixation du regard sur une page web ou un e-mail. (plus de détails ici), et bien sûr dans le domaine des SIG.
Dans le domaine de la géographie, il s'agit donc d'une
méthode de représentation des données en fonction de leur densité spatiale.
Si vous souhaitez ajouter une heatmap dans vos applications
web cartographiques, deux options sont possibles :
- pré-calculer la heatmap avec ArcGIS for Dekstop, publier le résultat sous forme de service web MapService) et ajouter le MapService dans la carte.
- offrir un outil dynamique à votre application web. Si les données ponctuelles sont mises à jour la heatmap s'adaptera automatiquement
La librairie heatmap.js
Nous allons voir ici comment assurer cette fonctionnalité de
génération de heatmap à la volée dans une application web JavaScript, grâce à
une librairie open source crée par Patrick Wied.
La librairie heatmap.js est
une librairie JavaScript qui exploite les Canvas HTML5 afin d'afficher des
heatmap au rendu fort appréciable dans votre appli web. La Heatmap est calculé
côté client (navigateur) et ne requiert aucun plugin. Le seul pré requis étant que
le navigateur supporte les Canvas HTML5 (ce que font les navigateurs récents, y
compris sur les périphériques mobiles). Cette librairie est sous licence opensource de type MIT and the Beerware license, vous
êtes donc libres de l'utiliser. Elle est également disponible
sur github, vous pouvez donc faire remonter vos impressions et remarque auprès
de son concepteur, mais également contribuer à son évolution.
Son principe de fonctionnement est le suivant : la heatmap
est générée dynamiquement d'après vos données ponctuelles qui peuvent provenir
d'une couche graphique (que vous aurez pris soin de remplir par une requête par
exemple). vous pouvez donc mettre à profit les featureLayers de l'ArcGIS API for JavaScript (qui sont
assimilables à des graphicsLayers remplis automatiquement par une requête pré-définie).
La heatmap se base sur cette collection de points. A chaque fois qu'un
point est ajouté à la collection, un processus vérifie si la valeur maximum a
changé et appelle une fonction de dessin du gradient de couleur (qui est fonction
des valeurs min et max de la collection).
Si par exemple la collection en contient qu'un seul point,
il sera afficher avec la plus forte valeur. Si un nouveau point y est ajoutées,
les valeur min et max seront recalculée dynamiquement, donc le gradient aussi,
donc la heatmap est mise à jour. La heatmap ajoutée par code à votre application
web est entièrement personnalisable en terme de gradient de couleur,
transparence, rayon de calcul etc...
Ajout d'une heatmap dynamique à votre application web
Partons d'une application très simple contenant une carte.
Cette carte est constituée d'une basemap (par exemple la World Topo Map Esri).
Dans l'ordre, il faut d'abord inclure les librairies JavaScript
nécessaires : heatmap.js (qui permet d'afficher une heatmap à partir d'un
tableau de points) et heatmap-arcgis.js (qui
permet de faire le lien entre cette librairie heatmap.js et l'ArcGIS API
for JavaScript).
Nous avons ensuite besoin de définir l'élément HTML qui contiendra
le fameux HTML Canvas d'HTML5 crée à la volée par la librairie heatmap.js.
<div id=”heatLayer”></div>
A présent nous pouvons créer, via la partie Javascript de
notre page HTML, la heatmap en spécifiant le rayon de traitement, le gradient
de couleur, la transparence. Un paramètre (useLocalMaximum) permet également de
spécifier la manière dont la valeur maximun est calculées : soit en tenant
compte de l'ensemble des données de la couche ponctuelle, soit en tenant compte
uniquement des données visibles dans l'étendue affichée.
heatLayer = new HeatmapLayer({
config: {
"useLocalMaximum": true,
"radius":
40,
"gradient": {
0.45:
"rgb(000,000,255)",
0.55:
"rgb(000,255,255)",
0.65:
"rgb(000,255,000)",
0.95:
"rgb(255,255,000)",
1.00:
"rgb(255,000,000)"
}
},
"map": map,
"domNodeId":
"heatLayer",
"opacity":
0.85
});
Le paramètre domNodeId doit avoir pour valeur le nom de l'élément HTML qui accueillera la heatmap.
N'oublions pas d'ajouter cette nouvelle couche à la carte : map.AddLayer(heatLayer);
Tout est prêt, il suffit à présent de remplir la couche.
Comment remplir notre heatLayer? A vous de choisir, mais un moyen simple est de réaliser une requête au serveur ArcGIS puis de "câbler" le résultat de cette requête sur la heatLayer.
Nous avons choisi ici d'utiliser des données référencées sur le portail OpenGeoData.fr : la couche des arrêts du réseau de transport en commun de la région Bordelaise (détails ici : http://www.opengeodata.fr/home/item.html?id=6a59850d794e46ab9af9df2cdb275246)
La couche de points que nous souhaitons afficher sous forme de heatmap est également affichée dans la carte sous forme de featureLayer.
Pour rappel, une featureLayer dérive des graphicsLayer. Une graphicsLayer permet de gérer côté client , donc localement dans votre navigateur, des objets graphiques (géométrie + attributs + symbologie) et de les afficher sur la carte. Une featureLayer est une graphicsLayer avec un comportement particulier qui est de se remplir quasi automatiquement. Elle possède pour cela une url (l'url d'un service de carte dynamique ou d'un service d'entités ArcGIS for Server, ou bien enfin d'une service d'entités hébergé sur ArcGIS Online). Une fois cette featureLayer ajoutée à la map, elle sera remplie via une requête sur le service web associé.
Notre featureLayer est en mode "ondemand", c'est à dire que seuls les points contenus dans l'étendue d'affichage sont stockés localement après requête au serveur. A chaque fois que l'étendue est mise à jour, la requête est automatiquement exécutée et la couche remplie.
Nous allons donc procéder de la même manière pour la heatLayer, ce qui nous permettra d'assurer le côté dynamique. A chaque fois qu'un point est ajouté à la featureLayer, il devra être ajouté à la heatLayer pour que la heatmap soit mise à jour (gradient recalculé, etc...).
Nous définissons donc une fonction getFeature() qui se chargera de faire la requête auprès du server, et d'envoyer le résultat (les points) à la heatLayer. Cette fonction sera appelée à chaque fois que l'étendue de la carte est mise à jour. donc on lie cette fonction à l'évènement onExtentChange de l'objet map.
function getFeatures() {
// la requête
var query = new
esri.tasks.Query();
// seulement pour
l'étendue
query.geometry = map.extent;
// on veut uniquement les
arrêts de la commune de Bordeaux
query.where = "ville =
'BORDEAUX'";
query.outSpatialReference
= map.spatialReference;
// on execute la
requête
featureLayer.queryFeatures(query, function (featureSet) {
var data = [];
// s'il y a un
résultat
if (featureSet
&& featureSet.features && featureSet.features.length > 0) {
// on met le résultat dans
un objet data
data = featureSet.features;
}
// que l'on envoie à notre
heatLayer
heatLayer.setData(data);
});
}
puis :
dojo.connect(map, "onExtentChange", getFeatures);
Simple, efficace, rapide et beau.
Libre à vous d'adapter le code pour offrir plus de fonctionnalités à l'utilisateur final (comme par exemple une belle interface afin de définir le gradient de couleurs, le rayon d'analyse, la couche à laquelle la heatmap est associée, etc...).
En conclusion, cette fonctionnalité se retrouve dans toutes les API web ArcGIS puisque c'est aussi possible en Silverlight et Flex.
Vous avez donc vu ici comme grâce à cette librairie, vous pouvez enrichir votre application web JavaScript avec une heatmap dynamique en quelques lignes de codes et surtout l'exploiter sur votre navigateur web ou sur votre smartphone ou tablet tactile préférée.
Les heatmap dynamiques sont donc à la portée de tous.
0 comments :
Enregistrer un commentaire