Makina Blog

Le blog Makina-corpus

Carte des vélos de Toulouse avec Leaflet


Les bookmarks, un peu comme les cahiers de recettes…

Les bookmarks, un peu comme les cahiers de recettes, c'est bien de les remplir mais encore faut-il trouver les bons au moment adéquate ! Même quand il s'agit d'outils, de bibliothèques et de services Web, il faut trouver l'occasion de les tester avant le grand soir ! Et si on veut en faire un article de blog, alors là, il faut en plus donner envie d'y goûter :)

Ici, je prends plein d'ingrédients trouvés au bord des chemins :

Je secoue bien fort ! (sans oublier de saupoudrer de jquery) et j'obtiens une carte interactive des stations vélos de Toulouse !

La liste des stations

Sur le site http://velonow.info, je récupère un fichier XML qui contient la liste statique des stations de vélo et leurs identifiants.

C'est l'occasion d'utiliser pyquery pour le transformer en GeoJSON. Gawel nous l'avait présenté aux djangocongs, il s'agit du portage de l'API de JQuery en python !

from pyquery import PyQuery as pq

d = pq(url='http://server.com/file.xml')
for m in map(lambda e: pq(e), d.find('marker')):
    pt = geojson.Point([m.attr('lng'),
                        m.attr('lat')])
    ...
    ...

Je trouve ça génial d'avoir la même syntaxe de manipulation du DOM en python et en javascript ! Et pour faire du webscrapping, c'est top !

Affichage de la carte

Cloudmade a créé leaflet qui rejoint Tile5 et Polymaps en tant que challenger d'Openlayers !

C'est une bibliothèque légère, jolie, fluide, optimisée pour les mobiles, et même compatible Internet Explorer !

Pour afficher une carte centrée sur la localisation du visiteur de la page, il suffit de faire ça :

var map = new L.Map('map');

var cloudmadeUrl = 'http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png',
    cloudmade = new L.TileLayer(cloudmadeUrl);

map.addLayer(cloudmade);
map.locateAndSetView();

Pour l'instant, Leaflet ne gère pas les couches au format GeoJSON, en attendant la prochaine release, nous allons ajouter les points des stations en 2 coups de cuillère à pot :

$.getJSON(url, function(data) {
    $.each(data.features, function(i, f) {
        var cc = f.geometry.coordinates;
        var marker = new L.Marker(new L.LatLng(cc[1], cc[0]));
        map.addLayer(marker);
    });
});

Détails d'une station en popup

Les détails d'une station (nombre de vélos, emplacements, libres, occupés) sont disponibles en fournissant un identifiant sur le site de velo toulouse. Mais lorsqu'on appelle la page en Ajax, le corps de la réponse XML est vide. Une protection contre la bidouillabilité sûrement.

C'est là que Yahoo Query Language nous aide ! On passe par Yahoo pour accèder aux ressources du Web avec des requêtes similaires aux bases de données !

var yql = "select * from xml where url = '" + url + "'",
 yqlurl = 'http://query.yahooapis.com/v1/public/yql?q=' + encodeURIComponent(yql);
$.get(yqlurl, function(data) {
    // show data in pop up !
});

Je fais une petite fonction pour transformer l'XML récupéré en objet :

function xml2obj(xmldata) {
    d = {};
    $(xmldata).children().each(function(index, value){
        d[$(value).get(0).nodeName] = $(value).text();
    });
    return d;
}
<station>
    <free>12</free>
    <available>4</available>
    <total>16</total>
</station>

devient :

{
    free : 12,
    available : 4,
    total: 16
}

Pour mettre en forme ces informations dans la pop-up, nous allons utiliser mustache ! Conceptuellement, il s'agit tout simplement d'un moteur de template avec une syntaxe simplifiée ! Il y a une implémentation dans quasiment tous les languages, dont Javascript.

Cela évite principalement de faire du code javascript pour la mise en forme des données, notamment pour celles récupérées en JSON via Ajax.

On construit une chaîne avec les fameuses {{}} et on fournit un objet pour substituer les valeurs :

var data = xml2obj($(xmldata).find('station')),
    template = "<h2>Station #{{ number }}</h2>
 <p>{{ address }}</p> 
 {{# station }} 
 <ul> 
 <li>{{ available }} available</li> 
 <li>{{ free }} free slots</li> 
 </ul> 
 {{/ station }}",
    content = Mustache.to_html(template, data);
// Show marker popup !
marker.bindPopup(content).openPopup();

Et voilà !

Actualités en lien

Image
Capture d'une partie de carte montrant un réseau de voies sur un fond de carte sombre. Au centre, une popup affiche les information de l'un des tronçons du réseau.
28/02/2024

Géné­rer un fichier PMTiles avec Tippe­ca­noe

Exemple de géné­ra­tion et d’af­fi­chage d’un jeu de tuiles vecto­rielles en PMTiles à partir de données publiques.

Voir l'article
Image
Drupal_Leaflet_SIG
11/05/2015

Web mapping avec Drupal et Leaflet

L'intégration de @LeafletJS avec #drupal est vraiment très rapide à mettre en œuvre.

Voir l'article
Image
Django_leaflet_GeoDjango
03/09/2013

Des cartes avec GeoDjango et Leaflet

Un guide pas à pas pour visualiser vos modèles Django avec Leaflet.

Voir l'article

Inscription à la newsletter

Nous vous avons convaincus