source: spip-zone/_plugins_/gis/trunk/modeles/carte_gis.html @ 69451

Last change on this file since 69451 was 69451, checked in by marcimat@…, 7 years ago

Option du modèle « carte_gis » pour faire du clustering JS côté Client en ajoutant le paramètre cluster=oui.
Un cluster étant un regroupement de points proches géographiquement, dans une case indiquant avec le nombre d'élément regroupés.

On s'appuie pour cela en grande partie du travail de b_b sur GeoDiversité? et sur la lib LeafClusterer? qu'il a adapté là https://github.com/brunob/leafclusterer .

Par ailleurs,

  • Des commentaires en plus
  • Boucle DATA pour les tests sur les args
  • On mutualise le code modifié qui peut l'être entre avec / sans cluster

2 options de plus :

  • clusterMaxZoom=11 pour indiquer que le clustering ne se fait plus à partir de ce niveau de zoom. Par défaut : (maxZoom - 2) (si maxZoom est défini) (à voir si on laisse comme ça ou pas)
  • clusterStyles=#ARRAY... pour modifier les styles des clusters

Ainsi, l'appel suivant fonctionne correctement :
[(#INCLURE{fond=modeles/carte_gis,

objets=articles,
id_rubrique=#ID_RUBRIQUE,
zoom=#CONFIG{gis/zoom},
maxZoom=13,
lat=#CONFIG{gis/lat},
lon=#CONFIG{gis/lon},
hauteur=600px,
controle_type=non,
cluster=non,
clusterStyles=[(#ARRAY{

url,#CHEMIN{images/bg_cluster.png},
height,40,
width,40,
opt_textColor,#ffffff})],

kml=[(#LISTE{

[(#CHEMIN{kml/16.kml}|timestamp|url_absolue)],
[(#CHEMIN{kml/17.kml}|timestamp|url_absolue)],
[(#CHEMIN{kml/86.kml}|timestamp|url_absolue)],
[(#CHEMIN{kml/79.kml}|timestamp|url_absolue)]})]})]

File size: 14.1 KB
Line 
1[(#REM)
2
3Modele carte_gis
4----------------
5
6Parametres possibles :
7
8- id_map|id_carte_gis = 1          id de la carte
9- lat|latit|latitude = 48.3        latitude du centre de la carte
10- lon|lonxit|longitude = -4.7      longitude du centre de la carte
11- zoom = 5                         zoom de la carte
12- maxZoom = 13                     zoom maximum autorisé
13
14- sw_lat = lat - 10°               latitude du sud-ouest de la bounding box
15- sw_lon = lon - 10°               longitude du sud-ouest de la bounding box
16- ne_lat = lat + 10°               latitude du nord-est de la bounding box
17- ne_lon = lon + 10°               longitude du nord-est de la bounding box
18
19- titre_carte                      titre affiché au dessus la carte
20- width|largeur = 100%             largeur de la carte, 100% par defaut
21- height|hauteur = 400px           hauteur de la carte, 400px par defaut
22- style = non                      ne pas styler la carte
23
24- fullscreen = oui                     afficher un bouton pour passer la carte en plein écran
25- zoom_molette|zoom_wheel = non        désactiver le zoom avec la molette de la souris, actif par defaut
26- control_type|controle_type = non     ne pas afficher les controles de changement de type
27- no_control|aucun_controle = oui      ne pas afficher les controles de la carte
28- scale = oui                          afficher l'échelle de la carte
29- overview = oui                       afficher une mini carte de situation
30
31- autocenterandzoom|centrer_auto = oui        centrer et zoomer la carte automatiquement pour afficher tous les marqueurs
32- localize_visitor|localiser_visiteur = oui   centrer la carte sur la position du visiteur (API geolocation HTML5)
33
34- objets = gis                     type d'objets à afficher (fichier json/gis_xx qui génère la source de donnees)
35- limit|limite = 500               nombre max de marqueurs à afficher, 500 par defaut
36- kml = 12                         kml à superposer à la carte (id_document ou url ou liste d'url)
37- gpx = 12                         gpx à superposer à la carte (id_document ou url ou liste d'url)
38- centrer_fichier = non            permet de ne pas centrer la carte automatiquement sur les fichiers kml/gpx surperposés
39- point = non                      si elle vaut "non" cette option n'affichera pas de points du tout (utile pour n'afficher qu'un kml par exemple)
40
41- media = non                      permet de passer le critère 'media' (pour les documents)
42- path_styles=#ARRAY{color,#fff}   options de style des éléments de la couche GeoJSON (voir http://leafletjs.com/reference.html#path-options)
43
44Uniquement si objets = point_libre :
45- icone = chemin/vers/image        image utilisée pour le marker
46- titre                            titre du point
47- description                      description du point
48
49Clustering (regroupement de points proches) :
50- cluster = oui                    Active le clustering
51- clusterMaxZoom = 11              Regroupe les points jusque à ce zoom, mais pas au delà
52- clusterStyles = #ARRAY{}         Styles appliqués aux clusters
53
54]
55
56[(#SET{width,#ENV{width,#ENV{largeur,100%}}})]
57[(#SET{height,#ENV{height,#ENV{hauteur,400px}}})]
58[(#SET{id,#ENV{id_carte_gis,#ENV{id_map,#ENV{id,1}}}})]
59[(#REM) -- compat gis v1 -- ]
60[(#SET{lat,#ENV{lat,#ENV{latit,#ENV{latitude,#CONFIG{gis/lat,0}}}}})]
61[(#SET{lon,#ENV{lon,#ENV{lonxit,#ENV{longitude,#CONFIG{gis/lon,0}}}}})]
62[(#REM) On utilise la bounding box seulement si le centre n'a pas été donné et si les quatre valeurs de la bounding box sont renseignées
63    les valeurs par defaut sont "centre +/- 10°", ce qui est naze, mais c'est un cas normalement impossible
64]
65[(#ENV{lat}|ou{#ENV{lon}}|non|et{#ENV{sw_lat}}|et{#ENV{sw_lon}}|et{#ENV{ne_lat}}|et{#ENV{ne_lon}})
66        #SET{utiliser_bb, oui}
67        #SET{sw_lat,#ENV{sw_lat,#GET{lat}|moins{10}}}
68        #SET{sw_lon,#ENV{sw_lon,#GET{lon}|moins{10}}}
69        #SET{ne_lat,#ENV{ne_lat,#GET{lat}|plus{10}}}
70        #SET{ne_lon,#ENV{ne_lon,#GET{lon}|plus{10}}}
71]
72
73[<h3>(#ENV{titre_carte})</h3>]
74<div id="map[(#GET{id})]" class="carte_gis p"[(#ENV{style}|!={'non'}|?{' '})style="[width:(#GET{width});][ height:(#GET{height});]"]></div>
75
76<script type="text/javascript">/*<!\[CDATA\[*/
77
78var map[(#GET{id})];
79
80(function($){
81
82        var init_map[(#GET{id})] = function(callback) {
83                var map_container = 'map[(#GET{id})]';
84
85                // Création de la carte Leafleat
86                map[(#GET{id})] = new L.Map(map_container,{
87                        scrollWheelZoom: [(#ENV{zoom_molette,#ENV{zoom_wheel}}|=={non}|?{false,true})],
88                        zoomControl: [(#ENV{no_control,#ENV{aucun_controle}}|!={oui}|?{true,false})][,
89                        maxZoom: (#ENV{maxZoom})]
90                });
91
92                // Appeler l'éventuelle fonction de callback
93                if (callback && typeof(callback) === "function") {
94                        map[(#GET{id})].on('load',function(e){
95                                callback(e.target);
96                        });
97                }
98
99                // Déterminer la position initiale de la carte
100                [(#GET{utiliser_bb}|non)
101                map[(#GET{id})].setView(new L.LatLng([(#GET{lat})], [(#GET{lon})]), [(#ENV{zoom,#CONFIG{gis/zoom,0}})]);]
102
103                [(#GET{utiliser_bb}|oui)
104                map[(#GET{id})].fitBounds(
105                        new L.LatLngBounds(
106                                new L.LatLng([(#GET{sw_lat})], [(#GET{sw_lon})]),
107                                new L.LatLng([(#GET{ne_lat})], [(#GET{ne_lon})])
108                        )
109                );]
110
111                // Fond de carte par défaut (layer)
112                #SET{layer_defaut,#REM|gis_layer_defaut} #SET{layers,#EVAL{$GLOBALS['gis_layers']}}
113                var [(#GET{layer_defaut})] = [new (#GET{layers/#GET{layer_defaut}/layer})];
114                map[(#GET{id})].addLayer([(#GET{layer_defaut})]);
115
116                <B_layers>
117                // liste des fonds de carte possibles
118                var layers_control = new L.Control.Layers();
119                layers_control.addBaseLayer([(#GET{layer_defaut})],["(#GET{layers/#GET{layer_defaut}/nom})"]);
120                <BOUCLE_layers(DATA){source table, #GET{layers}}
121                        {si #ENV{control_type,#ENV{controle_type}}|!={non}}
122                        {si #ENV{no_control,#ENV{aucun_controle}}|!={oui}}
123                        {si #CONFIG{gis/layers,#ARRAY}|count|>{1}}>[
124                (#CLE|!={#GET{layer_defaut}}|et{#CLE|in_any{#CONFIG{gis/layers}}|oui})
125                layers_control.addBaseLayer([new (#LAYER)],"#NOM");]
126                </BOUCLE_layers>
127                map[(#GET{id})].addControl(layers_control);
128                // ajouter l'objet du controle de layers à la carte pour permettre d'y accéder depuis le callback
129                map[(#GET{id})].layersControl = layers_control;
130                // classe noajax sur le layer_control pour éviter l'ajout de hidden par SPIP
131                $(layers_control._form).addClass('noajax');
132                </B_layers>
133
134                map[(#GET{id})].setView(new L.LatLng(#GET{lat},#GET{lon}),#ENV{zoom,#CONFIG{gis/zoom,0}});
135
136                map[(#GET{id})].attributionControl.setPrefix('');
137
138                // Ajout des contrôles de la carte
139                [(#ENV{scale}|et{#ENV{no_control,#ENV{aucun_controle}}|!={oui}}|oui)
140                map[(#GET{id})].addControl(new L.Control.Scale());
141                ][(#ENV{fullscreen}|et{#ENV{no_control,#ENV{aucun_controle}}|!={oui}}|oui)
142                map[(#GET{id})].addControl(new L.Control.FullScreen());
143                ][(#ENV{overview}|et{#ENV{no_control,#ENV{aucun_controle}}|!={oui}}|oui)
144                var minimap_layer = [new (#GET{layers/#GET{layer_defaut}/layer})];
145                var miniMap = new L.Control.MiniMap(minimap_layer,{width: 100,height: 100}).addTo(map[(#GET{id})]);
146                ]
147
148                // Pour Ajouter l'icone d'un point (feature = item d'un GeoJson)
149                var setGeoJsonFeatureIcon = function (feature, layer) {
150                        // Déclarer l'icone du points, si défini
151                        if (feature.properties && feature.properties.icon){
152                                layer.setIcon(new L.Icon({
153                                        iconUrl: feature.properties.icon,
154                                        iconSize: new L.Point( feature.properties.icon_size\[0\], feature.properties.icon_size\[1\] ),
155                                        iconAnchor: new L.Point( feature.properties.icon_anchor\[0\], feature.properties.icon_anchor\[1\] )
156                                }));
157                        }
158                }
159
160                // Pour Ajouter le texte de popup d'un point (feature = item d'un GeoJson)
161                var setGeoJsonFeaturePopup = function (feature, layer) {
162                        // Déclarer le contenu de la popup s'il y en a
163                        if (feature.properties && (feature.properties.title || feature.properties.description)){
164                                var popupContent = '';
165                                if (feature.properties.title)
166                                        popupContent = '<strong class="title">' + feature.properties.title + '</strong>';
167                                if (feature.properties.description)
168                                        popupContent = popupContent + feature.properties.description;
169                                layer.bindPopup(popupContent);
170                        }
171                }
172
173                [(#REM)
174                        Il y a pour le moment 2 façons d'analyser le GeoJson calculé
175                        en fonction de si on veut faire du clustering (regrouper les points proches)
176                        ou non. Il y a certainement moyen de regrouper en un seul élément
177                        la plupart du code, en se passant du js L.geoJson même hors clustering.
178                        À réfléchir.
179                ]
180                <BOUCLE_fonction_analyse_json(CONDITION){si #ENV{cluster}|!={oui}}>
181                // Analyse des points et déclaration (sans regroupement des points en cluster)
182                var parseGeoJson = function(data, map) {
183                        var geojson = new L.geoJson('', {[
184                                style: (#ENV*{path_styles}|json_encode),
185                                ]onEachFeature: function (feature, layer) {
186                                        // Déclarer l'icone du point
187                                        setGeoJsonFeatureIcon(feature, layer);
188                                        // Déclarer le contenu de la popup s'il y en a
189                                        setGeoJsonFeaturePopup(feature, layer);
190                                }
191                        }).addTo(map);
192                        geojson.addData(data);
193                        [(#ENV{autocenterandzoom,#ENV{centrer_auto}}|oui)
194                        map.fitBounds(geojson.getBounds());]
195                }
196
197                </BOUCLE_fonction_analyse_json>
198
199                // Analyse des points et déclaration (en regroupant les points en cluster)
200                var parseGeoJson = function(data,map) {
201                        markers = \[\];
202                        /* Pour chaque points présents, on crée un marqueur */
203                        $.each(data.features, function(i, feature) {
204                                if (feature.geometry.coordinates\[0\]) {
205                                        var latlng = new L.LatLng(feature.geometry.coordinates\[1\], feature.geometry.coordinates\[0\]);
206                                        var marker = new L.Marker(latlng);
207                                        // Déclarer l'icone du point
208                                        setGeoJsonFeatureIcon(feature, marker);
209                                        // Déclarer le contenu de la popup s'il y en a
210                                        setGeoJsonFeaturePopup(feature, marker);
211
212                                        marker.id = feature.id;
213                                        markers.push(marker);
214                                }
215                        });
216
217                        /* Ajout des marqueurs dans un clustering JS client */
218                        markerCluster = new L.Marker.Clusterer(map, markers, {[
219                                maxZoom: (#ENV{clusterMaxZoom, #ENV{maxZoom}|?{#ENV{maxZoom}|moins{2},''}}),][
220                                styles: \[[(#ENV*{clusterStyles}|json_encode)]\](#ENV*{clusterStyles}|oui)]
221                        });
222                }
223                <//B_fonction_analyse_json>
224
225
226                <BOUCLE_definir_les_points_de_la_carte(CONDITION){si #ENV{point}|!={non}}>
227                [(#REM)
228                        \#ENV{args} est présent uniquement lors de l'appel d'un modèle <carte_gis|...>
229                        dans un texte et contient alors les paramètres passés au modèle manuellement.
230                        On considère dans ce cas que seuls ces paramètres doivent calculer le json,
231                        et non pas aussi l'environnement automatique ajouté au modèle (comme objet, id_objet)
232                        dans lequel le modèle est appelé.
233                ]
234                // Récupération des points à mettre sur la carte, via json externe
235                jQuery.getJSON("[(#URL_PAGE{gis_json}|url_absolue)]",
236                        {[
237                                objets       : "(#ENV{objets,#ENV{class}}|trim)",]
238                                <BOUCLE_modeles_args_prioritaires(DATA){source table,#LISTE{
239                                        id_objet, id_rubrique, id_secteur, id_parent,
240                                        id_article, id_breve, id_document, id_mot,
241                                        id_groupe, id_auteur, id_syndic, id_forum,
242                                        id_gis, id_evenement
243                                }}>[#VALEUR : (#ENV{args}|?{#ENV{args/#VALEUR},#ENV{#VALEUR}}|trim),
244                                ]</BOUCLE_modeles_args_prioritaires>[
245                                media        : "(#ENV{args}|?{#ENV{args/media},#ENV{media}}|trim)",][
246                                recherche    : "(#ENV{args}|?{#ENV{args/recherche},#ENV{recherche}})",][
247                                mots  : (#ENV{mots}|?{[(#ENV{mots}|trim|json_encode)],''}),][
248                                limit : (#ENV{limit,#ENV{limite,500}}|trim)][
249                                (#ENV{objets}|=={point_libre}|oui)
250                                        [,lat : (#GET{lat}|trim)]
251                                        [,lon : (#GET{lon}|trim)]
252                                        [,titre : (#ENV{titre}|json_encode)]
253                                        [,description : (#ENV{description}|json_encode)]
254                                        [,icone : (#ENV{icone}|json_encode)]
255                                ]
256                        },
257                        function(data) {
258                                if (data){
259                                        // Charger le json (data) et déclarer les points
260                                        parseGeoJson(data, map[(#GET{id})]);
261                                }
262                        }
263                );
264                </BOUCLE_definir_les_points_de_la_carte>
265
266
267                <BOUCLE_test_kml(CONDITION){si (#ENV{kml}|oui)}>
268                        // Définir les couches KML ajoutées à la carte
269                        #SET{kml, #ENV{kml}}
270                        [(#GET{kml}|is_array|non) #SET{kml, #ARRAY{0,#GET{kml}}} ]
271                        <BOUCLE_kml(POUR){tableau #GET{kml}}>
272                                [(#VALEUR|intval|oui)
273                                var kml_#COMPTEUR_BOUCLE = new L.KML(['(#VALEUR|generer_url_entite{document}|url_absolue)'], {async: true}); ]
274                                [(#VALEUR|intval|non)
275                                var kml_#COMPTEUR_BOUCLE = new L.KML(['(#VALEUR|copie_locale)'], {async: true}); ]
276                                [(#ENV{centrer_fichier}|!={non}|et{#TOTAL_BOUCLE|>{1}|non})
277                                kml_#COMPTEUR_BOUCLE.on("loaded", function(e) { map[(#GET{id})].fitBounds(e.target.getBounds()); });]
278                                map[(#GET{id})].addLayer(kml_#COMPTEUR_BOUCLE);
279                        </BOUCLE_kml>
280                </BOUCLE_test_kml>
281
282                <BOUCLE_test_gpx(CONDITION){si (#ENV{gpx}|oui)}>
283                        // Définir les couches GPX ajoutées à la carte
284                        #SET{gpx, #ENV{gpx}}
285                        [(#GET{gpx}|is_array|non) #SET{gpx, #ARRAY{0,#GET{gpx}}} ]
286                        <BOUCLE_gpx(POUR){tableau #GET{gpx}}>
287                                [(#VALEUR|intval|oui)
288                                var gpx_#COMPTEUR_BOUCLE = new L.GPX(['(#VALEUR|generer_url_entite{document}|url_absolue)'], {async: true}); ]
289                                [(#VALEUR|intval|non)
290                                var gpx_#COMPTEUR_BOUCLE = new L.GPX(['(#VALEUR|copie_locale)'], {async: true}); ]
291                                [(#ENV{centrer_fichier}|!={non}|et{#TOTAL_BOUCLE|>{1}|non})
292                                gpx_#COMPTEUR_BOUCLE.on("loaded", function(e) { map[(#GET{id})].fitBounds(e.target.getBounds()); });]
293                                map[(#GET{id})].addLayer(gpx_#COMPTEUR_BOUCLE);
294                        </BOUCLE_gpx>
295                </BOUCLE_test_gpx>
296
297                [(#ENV{localize_visitor,#ENV{localiser_visiteur}}|oui)
298                map[(#GET{id})].locate({setView: true, maxZoom: [(#ENV{zoom,#CONFIG{gis/zoom,0}})]});]
299
300        }
301
302
303        // Charger le javascript de GIS et initialiser la carte
304        $(function(){
305                jQuery.getScript(['(#CONFIG{auto_compress_js}|=={oui}|?{[(#PRODUIRE{fond=javascript/gis.js}|compacte)],[(#PRODUIRE{fond=javascript/gis.js})]})'],function(){
306                        [(#ENV{cluster}|=={oui}|oui)
307                                jQuery.getScript('[(#CHEMIN{javascript/leafclusterer.js}|compacte)]',function(){
308                        ]
309                                if (typeof(callback_map[(#GET{id})]) === "function") {
310                                        init_map[(#GET{id})](callback_map[(#GET{id})]);
311                                } else {
312                                        init_map[(#GET{id})]();
313                                }
314                        [(#ENV{cluster}|=={oui}|oui)
315                                });
316                        ]
317                });
318        });
319
320})(jQuery);
321/*\]\]>*/
322</script>
Note: See TracBrowser for help on using the repository browser.