Tutoriel : créer une carte interactive avec GIS4

Utilisation de quelques fonctions javascript pour créer des interactions avec une carte GIS.

L’objet de ce tutoriel est de produire une carte interactive.

Effacer tous les points d’une carte

La fonction javascript removeAllMarkers() permet d’effacer tous les points de la carte à laquelle elle est associée.

Exemple, pour effacer tous les articles de la carte map1 :
map1.removeAllMarkers();

Afficher des points sur une carte existante.

De la même manière, il est possible d’ajouter des points à une carte grâce à la fonction javascript parseGeoJson()

Cette fonction prend comme unique variable le contenu du Json à appliquer. Avec GIS, on pourra l’utiliser de la manière suivante en incluant les fichiers se trouvant dans le répertoire /json :

map1.parseGeoJson({"type": "FeatureCollection",	"features": [<INCLURE{fond=json/gis_monjson}{mavariable}>]});

Exemple d’utilisation de ces 2 fonctions :

Pour créer une carte :
-  affichant les logos des mots-clés associés aux articles
-  filtrable par logo de mots-clé

1./ On aligne une série de pictos comprenant :
-  les logos des mot-clés qui serviront de lien pour filtrer les points
-  d’un visuel qui servira de lien pour rétablir la carte initiale (images/tout.png)

<B_domaines>
<ul id="select">
<BOUCLE_domaines(MOTS){id_groupe=2}>
<li class="markermot[(#ID_MOT)]">#LOGO_MOT<br />[(#TITRE|supprimer_numero)]</li>
</BOUCLE_domaines>
<li class="toutmarker"><img alt="tous les points" src="[(#CHEMIN{images/tout.png})]" /><br />Tout</li>
</ul>
</B_domaines>

2./ On adapte un squelette Json qui permettra d’afficher tous les logos :

Nous créons donc un fichier gis_touslesmots dans squelettes/json :

<BOUCLE_art(ARTICLES){gis}{","}><BOUCLE_gis(GIS){id_article}{doublons}{","}>
		{"type": "Feature",
		"geometry": {"type": "Point", "coordinates": [#LON, #LAT]},
		"id":"#ID_GIS",
		"properties": {
			"title":[(#TITRE*|sinon{#_art:TITRE*}|supprimer_numero|json_encode)],
			"description":[(#DESCRIPTIF|sinon{#_art:INTRODUCTION}|textebrut|concat{... <a href="#_art:URL_ARTICLE">En savoir plus</a>}|replace{"'","\'"}|json_encode)][(#SET{logo_doc,''})]
			<BOUCLE_mot(MOTS){id_article=#_art:ID_ARTICLE}{id_groupe=2}{par hasard}{0,1}>[(#SET{logo_doc,#LOGO_MOT|image_passe_partout{32,32}})]</BOUCLE_mot>
			[(#GET{logo_doc}|oui)
			#SET{icon_w,#GET{logo_doc}|extraire_attribut{src}|largeur}
			#SET{icon_h,#GET{logo_doc}|extraire_attribut{src}|hauteur}
			[,"icon": (#GET{logo_doc}|extraire_attribut{src}|url_absolue|json_encode)],
			"icon_size": \[[(#GET{icon_w})],[(#GET{icon_h})]\],
			"icon_anchor": \[[(#GET{icon_w}|div{2})],[(#GET{icon_h})]\],
			"popup_anchor": \[1,[-(#GET{icon_h}|div{1.2})]\]]
		}}</BOUCLE_gis></BOUCLE_art>

Petites particularités :
-  Si le point ne possède pas de titre et/ou de descriptif, ceux-ci sont remplacés respectivement par le titre et/ou descriptif de l’article auquel ils sont associés.
-  Le descriptif se termine par un lien vers l’article auquel est associé le point

Ces 2 particularités expliquent la présence d’une boucle ARTICLES encadrant le code. Cette boucle est associé aux balises #_art:TITRE, #_art:INTRODUCTION et #_art:URL_ARTICLE.

3./ De la même manière, on crée un squelette Json permettant d’afficher les points géolocalisant les articles associés à un mot clé particulier. Nous l’appelons gis_articlesmot . Une variable id_mot est nécessaire à sa génération :

 
<BOUCLE_art(ARTICLES){gis}{id_mot}{","}><BOUCLE_gis(GIS){id_article}{doublons}{","}>
		{"type": "Feature",
		"geometry": {"type": "Point", "coordinates": [#LON, #LAT]},
		"id":"#ID_GIS",
		"properties": {
			"title":
[(#TITRE*|sinon{#_art:TITRE*}|supprimer_numero|json_encode)],
			"description":[(#DESCRIPTIF|sinon{#_art:INTRODUCTION}|textebrut|concat{... <a href="#_art:URL_ARTICLE">En savoir plus</a>}|replace{"'","\'"}|json_encode)][(#SET{logo_doc,''})]
			[(#SET{logo_doc,#LOGO_MOT{#ENV{id_mot}}|image_passe_partout{32,32}})]
			[(#GET{logo_doc}|oui)
			#SET{icon_w,#GET{logo_doc}|extraire_attribut{src}|largeur}
			#SET{icon_h,#GET{logo_doc}|extraire_attribut{src}|hauteur}
			[,"icon": (#GET{logo_doc}|extraire_attribut{src}|url_absolue|json_encode)],
			"icon_size": \[[(#GET{icon_w})],[(#GET{icon_h})]\],
			"icon_anchor": \[[(#GET{icon_w}|div{2})],[(#GET{icon_h})]\],
			"popup_anchor": \[1,[-(#GET{icon_h}|div{1.2})]\]]
		}}</BOUCLE_gis></BOUCLE_art>

4./ On affiche la carte qui fait apparaître tous les points en s’appuyant sur le premier des 2 squelettes Json.

  [(#MODELE{carte_gis,objets=touslesmots,id_groupe=2})]

5./ Enfin, ajoutons les fonctions javascript qui filtreront les points après un clic sur l’un des boutons générés ci-dessus.

<BOUCLE_domainesjs(MOTS){id_groupe=2}>
$('.markermot[(#ID_MOT)]').click(function(){
	map1.removeAllMarkers();
	map1.parseGeoJson({"type": "FeatureCollection",	"features": [<INCLURE{fond=json/gis_articlesmot}{id_mot=#ID_MOT}{limit=500}>]}	);
	$('#listedroite').load('[(#URL_PAGE{listedroite,id_mot=[(#ID_MOT)]}|replace{'&amp;amp;amp;','&amp;amp;'}|url_absolue)]');	
});
</BOUCLE_domainesjs>

Allons plus loin : générons une liste de liens permettant de faire apparaître les infobulles

6./ La liste apparaîtra en entier par défaut dans un cadre scrollable. Elle sera filtrée en même temps que les points.

Il faudra donc styliser la balise nommée “listedroite” avec un overflow: auto; , une hauteur et une largeur fixe.

<div id="listedroite">
<p style="margin-left:10px;">Cliquez sur un titre ci-dessous pour l'afficher sur la carte :</p>
<h2 id="gtitre"><img src="#CHEMIN{images/tout.png}" /> Tout</h2>
<hr style="height:1px;border:1px dashed #848284;margin:-6px 10px 0 10px;" />
<div style="width:180px;height:300px;overflow:auto;">
  <ul id="markers">
  <BOUCLE_artpoint10(ARTICLES){gis}{id_groupe=2}{par num titre,titre}>
      [<li><a href="#" class="infowindow[(#ID_ARTICLE)]">(#TITRE|supprimer_numero|unique)</a></li>]
  </BOUCLE_artpoint10>
  </ul>
</div>

7./ Nous modifierons les fonctions javascript ci-dessus pour filtrer les listes lors des clics sur les logos des mots-clé :

<B_domainesjs>
<script type="text/javascript"><!--
<BOUCLE_domainesjs(MOTS){id_groupe=2}>
$('.markermot[(#ID_MOT)]').click(function(){
	map1.removeAllMarkers();
	// Ajouter tous les curseur liés à un mot clé à l'aide des json du plugin GIS
	map1.parseGeoJson({"type": "FeatureCollection",	"features": [<INCLURE{fond=json/gis_articlesmot}{id_mot=#ID_MOT}{limit=500}>]}	);
	$('#listedroite').load('[(#URL_PAGE{listedroite,id_mot=[(#ID_MOT)]}|replace{'&amp;amp;amp;','&amp;amp;'}|url_absolue)]');	
});
</BOUCLE_domainesjs>
$('.toutmarker').click(function(){
	// Ajouter tous les curseur liés à l'aide d'un json personnalisé
	map1.parseGeoJson({"type": "FeatureCollection",	"features": [<INCLURE{fond=json/gis_touslesmots}{limit=500}>]}	);		
	$('#listedroite').load('[(#URL_PAGE{listedroite}|replace{'&amp;amp;amp;','&amp;amp;'}|url_absolue)]');	
});
--></script>
</B_domainesjs>

8./ Ces fonctions chargent la page suivante qu’il convient de placer dans le répertoire squelettes :

<BOUCLE_mot(MOTS){id_mot=#ENV{id_mot}}>
<td id="listedroite">
<p style="margin-left:10px;">Cliquez sur un titre ci-dessous pour l'afficher sur la carte :</p>
<h2 id="gtitre">[(#LOGO_MOT|image_reduire{19})] [(#TITRE)]</h2>
<hr style="height:1px;border:1px dashed #848284;margin:-6px 10px 0 10px;" />
<div style="width:180px;height:300px;overflow:auto;">
<ul id="markers">
  <BOUCLE_artpoint10(ARTICLES){gis}{id_mot}{par titre}>
  <BOUCLE_mot2(GIS){id_article}>
      [<lI><a href="#" class="infowindow[(#_artpoint10:ID_ARTICLE)]_[(#ID_GIS)]">(#TITRE|supprimer_numero|unique)</a></li>]
      <script type="text/javascript"><!--
      $('.infowindow[(#_artpoint10:ID_ARTICLE)]_[(#ID_GIS)]').click(function(){ gis_focus_marker(#ID_GIS,1); });
      --></script>
  </BOUCLE_mot2>
  </BOUCLE_artpoint10>
</ul>
</div>
</td>
</BOUCLE_mot>
<td id="listedroite">
<p style="margin-left:10px;">Cliquez sur un titre ci-dessous pour l'afficher sur la carte :</p>
<h2 id="gtitre"><img src="#CHEMIN{images/tout.png}" /> Tout</h2>
<hr style="height:1px;border:1px dashed #848284;margin:-6px 10px 0 10px;" />
<div style="width:180px;height:300px;overflow:auto;">
<ul id="markers">
<BOUCLE_artpoint102(ARTICLES){gis}{id_groupe=2}{par titre}>
    [<li><a href="#" class="infowindow[(#ID_ARTICLE)]">(#TITRE|supprimer_numero|unique)</a></li>]
<script type="text/javascript"><!--
$('.infowindow[(#ID_ARTICLE)]').click(function(){<BOUCLE_mot22(GIS){id_article}>		gis_focus_marker(#ID_GIS,1):</BOUCLE_mot22>});
--></script>
</BOUCLE_artpoint102>
</ul>
</div>
</td>
<//B_mot>

Et voila, c’est fini pour aujourd’hui.

Discussion

13 discussions

  • 1

    Quelques petites questions :

    1) Mes mots-clés sont associés aux rubriques. Les articles ont la liaison gis. Comment afficher les articles de la rubrique avec le mot clé (et donc le marqueur) associé ?

    Ceci m’affiche bien les lieux liés à des articles, mais pas le contenu des articles. Le titre est celui du lieu par exemple. (J’ai allégé le code entre les boucles)

    <BOUCLE_art(RUBRIQUES){id_mot}{","}>
    <BOUCLE_arti(ARTICLES){id_rubrique}{gis}{","}>
    <BOUCLE_gis(GIS){id_article}{doublons}{","}>
    {"type": "Feature",
    "geometry": {"type": "Point", "coordinates": [#LON, #LAT]},
    "id":"#ID_GIS",
    "properties": {
    "title":
    [(#TITRE*|sinon{#_art:TITRE*}|supprimer_numero|json_encode)],
    </BOUCLE_gis>
    </BOUCLE_arti>
    </BOUCLE_art>

    2) Puis-je mettre une autre boucle dans le même fichier, appelant des données externes XML.
    ? Ces données sont liées à des rubriques aussi mais n’utilisent bien sûr pas GIS.

    <BOUCLE_rub(RUBRIQUES){gis}{id_mot}{","}>
    #SET{xml, moxml#ID_RUBRIQUE.xml}
    #SET{trier,#ARRAY}
    <BOUCLE_gis2(DATA)
    {source simplexml, #GET{xml}}
    {datapath root/children/resultat/0/children/sit_liste}
    {","}>
    #SET{photo,''}
    <BOUCLE_photos(DATA)
    {source tableau,#VALEUR{children/criteres/0/children/crit}}
    {attributes/clef_critere = 30000279}>
    #SET{photo,#VALEUR{text}}
    </BOUCLE_photos>
    {"type": "Feature",
    "geometry": {"type": "Point", "coordinates": [
    #VALEUR{children/longitude/0/text}, 
    #VALEUR{children/latitude/0/text}]},
    "id":"#VALEUR{children/produit/0/text}",
    "properties": {
    "title":[(#VALEUR{children/nom/0/text}|json_encode)],
    "description":[(#GET{photo}|sinon{''}|json_encode)][(#SET{logo_doc,''})]
    }}
    </BOUCLE_gis2>
    </BOUCLE_rub>

    Là je n’ai strictement rien à l’affichage...

    Merci pour les idées de correction :)

    • Réponse à moi-même (et les autres) pour la question n°1. Pour avoir les bonnes données je dois bien nommer la balise s’associant aux articles. Donc pas #_art:TITRE* mais #_arti:TITRE*

      Reste la question 2 :)

    Reply to this message

  • Très intéressant, merci pour cet article.

    Je cherchais à créer une carte GIS en lui transmettant soit des paramètres (pas prévus dans le modèle carte_gis), soit en lui passant carrément une liste de points pré-calculés.

    Cet article m’a mis sur la bonne voie, mais pour charger automatiquement la liste de point au démarrage et pas au clic, il faut se baser sur l’évènement « ready », exemple :

    $('#map1').on('ready',function(){
       map1.parseGeoJson({"type": "FeatureCollection",        "features": [<INCLURE{fond=json/gis_mon_json}{liste=#GET{mon_tableau}|json_encode}>]});
    });

    Et par sécurité, pour être sûr de bien s’adresser à #map1 et map1, il vaut mieux passer l’identifiant de la carte en dur dans l’appel au modèle :

    [(#MODELE{
       carte_gis, id_carte_gis=1,
       ...
    })]

    Par contre, les clusters réagissent un peu différemment dans le cas où on lance un parseGeoJson après chargement de la carte.

    Reply to this message

  • 1

    Je suggère de renommer cet article (très intéressant) “Tutoriel: créer une carte interactive avec GIS4”. Merci !

    Reply to this message

Add a comment

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite / PostgreSQL
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparait.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Who are you?
[Log in]

To show your avatar with your message, register it first on gravatar.com (free et painless) and don’t forget to indicate your Email addresse here.

Enter your comment here

This form accepts SPIP shortcuts {{bold}} {italic} -*list [text->url] <quote> <code> and HTML code <q> <del> <ins>. To create paragraphs, just leave empty lines.

Add a document

Follow the comments: RSS 2.0 | Atom