Accueil / Blog / Métier / Archives / Carte des vélos de Toulouse avec Leaflet

Carte des vélos de Toulouse avec Leaflet

Par Mathieu Leplatre publié 31/05/2011

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à !

ABONNEZ-VOUS À LA NEWSLETTER !
Voir aussi
How to setup Angular Universal How to setup Angular Universal 29/06/2017

Step by step explanation. All the pitfalls to avoid.

Comment mettre en place Angular Universal Comment mettre en place Angular Universal 29/06/2017

Toutes les étapes détaillées et expliquées. Les pièges à éviter.

SEO : indexing a JavaScript application SEO : indexing a JavaScript application 29/06/2017

How to produce a server-side rendered version of your web application.

SEO : indexer une application Javascript SEO : indexer une application Javascript 29/06/2017

Comment utiliser le code de votre application pour un rendu server-side.

Découverte de React Native Découverte de React Native 18/04/2016

Présentation de React Native, quelles sont ses possibilités et peut-on l'utiliser en prod ?