« Questionnaire carto avec Limesurvey » : différence entre les versions
Aller à la navigation
Aller à la recherche
Aucun résumé des modifications |
Aucun résumé des modifications |
||
Ligne 1 : | Ligne 1 : | ||
À la demande d'une doctorante, j'ai rédigé ce petit bout de code en Javascript permettant d'intégrer une question de type ''Tracez un polygone sur la carte'' dans un questionnaire Limesurvey. | À la demande d'une doctorante, j'ai rédigé ce petit bout de code en Javascript permettant d'intégrer une question de type ''Tracez un polygone sur la carte'' dans un questionnaire Limesurvey. | ||
Ce code est à insérer dans l'énoncé d'une question de type texte long. La réponse sera générée automatiquement par Leaflet : il s'agira d'un geojson contenant le polygone tracé par l'utilisateur.<syntaxhighlight lang="html"> | |||
<!-- | |||
Ce code est à insérer dans l'énoncé d'une question de type texte long. La réponse sera générée automatiquement par Leaflet : il s'agira d'un geojson contenant le polygone tracé par l'utilisateur. | |||
== Version 1 - éditeur vectoriel classique == | |||
<syntaxhighlight lang="html"> | |||
<!-- Leaflet --> | |||
<link href="https://unpkg.com/leaflet@1.9.1/dist/leaflet.css" rel="stylesheet" /> | <link href="https://unpkg.com/leaflet@1.9.1/dist/leaflet.css" rel="stylesheet" /> | ||
<script src="https://unpkg.com/leaflet@1.9.1/dist/leaflet.js"></script> | <script src="https://unpkg.com/leaflet@1.9.1/dist/leaflet.js"></script> | ||
<!-- | <!-- Leaflet Draw --> | ||
<link href="https:// | <link href="https://unpkg.com/leaflet-draw@1.0.4/dist/leaflet.draw.css" rel="stylesheet" /> | ||
<script src="https://unpkg.com/leaflet-draw@1.0.4/dist/leaflet.draw.js"></script> | |||
<script src="https:// | |||
<!-- | <!-- Leaflet Search --> | ||
<link href="https://unpkg.com/leaflet-search@3.0.3/dist/leaflet-search.src.css" rel="stylesheet" /> | <link href="https://unpkg.com/leaflet-search@3.0.3/dist/leaflet-search.src.css" rel="stylesheet" /> | ||
<script src="https://unpkg.com/leaflet-search@3.0.3/dist/leaflet-search.src.js"></script> | <script src="https://unpkg.com/leaflet-search@3.0.3/dist/leaflet-search.src.js"></script> | ||
Ligne 110 : | Ligne 109 : | ||
}); | }); | ||
</script> | </script> | ||
</syntaxhighlight> | |||
== Version 2 - éditeur de type "pinceau à polygones" == | |||
<syntaxhighlight lang="html"> | |||
<!-- Leaflet --> | |||
<link href="https://unpkg.com/leaflet@1.9.1/dist/leaflet.css" rel="stylesheet" /> | |||
<script src="https://unpkg.com/leaflet@1.9.1/dist/leaflet.js"></script> | |||
<!-- Leaflet Search --> | |||
<link href="https://unpkg.com/leaflet-search@3.0.3/dist/leaflet-search.src.css" rel="stylesheet" /> | |||
<script src="https://unpkg.com/leaflet-search@3.0.3/dist/leaflet-search.src.js"></script> | |||
<!-- Leaflet Paint-Polygon by Thibault Coupin --> | |||
<script src="https://cdn.jsdelivr.net/npm/leaflet-paintpolygon@1.2.1-alpha.1/dist/Leaflet.PaintPolygon.min.js"></script> | |||
<!-- CSS pour la taille de la carte et pour cacher le formulaire de réponse --> | |||
<style type="text/css"> | |||
#map { | |||
height: 500px; | |||
} | |||
.answer-container { | |||
display:none; | |||
} | |||
</style> | |||
<!-- Question --> | |||
Carte : | |||
<div id="map"> </div> | |||
<!-- JS de la carte --> | |||
<script type="text/javascript" charset="utf-8"> | |||
// Paramètres de la carte de base | |||
var map = L.map('map', { | |||
crs: L.CRS.EPSG3857, | |||
minZoom: 5, | |||
maxZoom: 18, | |||
}).setView([45.763, 4.732], 13); | |||
// Ajout de la fonction de recherche | |||
map.addControl(new L.Control.Search({ | |||
url: 'https://nominatim.openstreetmap.org/search?format=json&q={ s }', | |||
jsonpParam: 'json_callback', | |||
propertyName: 'display_name', | |||
propertyLoc: ['lat', 'lon'], | |||
marker: L.circleMarker([0, 0], { radius: 1 }), | |||
autoCollapse: true, | |||
autoType: false, | |||
minLength: 2 | |||
})); | |||
// Ajout de la couche WMS géoportail | |||
var wmsGeoportail = L.tileLayer.wms('https://wxs.ign.fr/cartes/geoportail/r/wms?SERVICE=WMS&VERSION=1.3.0&CRS=EPSG:3857', { | |||
layers: 'GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2', | |||
attribution: 'IGN-F' | |||
}).addTo(map); | |||
// Définir une FeatureCollection pour les polygones tracés | |||
var drawnItems = new L.FeatureGroup(); | |||
map.addLayer(drawnItems); | |||
// Définir le style de la couche | |||
var myStyle = { | |||
"color": "#ff7800", | |||
"weight": 5, | |||
"opacity": 0.65 | |||
}; | |||
drawnItems.setStyle(myStyle); | |||
// Ajout du pinceau à polygones | |||
var paintControl = L.control.paintPolygon({position: 'topleft'}); | |||
paintControl.addTo(map); | |||
function updateDrawnItems(){ | |||
var JSONoutput = JSON.stringify(paintControl.getData()); | |||
$('#answer{SGQ}').val(JSONoutput); | |||
} | |||
setInterval('updateDrawnItems()', 1000); // Mise à jour des entités tracées toutes les secondes | |||
</script> | |||
</syntaxhighlight> | |||
== Script R pour extraire les entités vectorielles des résultats LimeSurvey == | |||
<syntaxhighlight lang="r"> | |||
library(dplyr) | |||
library(sf) | |||
library(geojsonsf) | |||
# Lire les résultats de l'enquête | |||
data = read.csv('./results-survey.csv') %>% as_tibble() | |||
# Definir une fonction pour ajouter l'id limesurvey à une collection de géométries sf | |||
add_id = function(sf, id) { | |||
sf = sf %>% mutate(id_limesurvey = id) | |||
return(sf) | |||
} | |||
###### | |||
### Dans toutes les lignes suivantes, remplacez "QUESTIONID" par le nom du champ contenant les géométries à extraire | |||
###### | |||
geom_table = data %>% | |||
filter(grepl("\"type\":\"FeatureCollection\"", QUESTIONID)) %>% # Filtrer les réponses où des géométries ont été saisies | |||
select(QUESTIONID, id) %>% | |||
mutate(sf = lapply(QUESTIONID, geojson_sf), # Convertir le geojson en objets sf | |||
sf = mapply(add_id, sf, id, SIMPLIFY = FALSE)) # Appliquer la fonction add_id pour ajouter l'id_limesurvey | |||
# Fusionner toutes les géométries dans un seul objet sf | |||
geometries = bind_rows(geom_table$sf) | |||
# Ecrire l'objet sf dans un geopackage | |||
st_write(geometries, dsn = './QUESTIONID.gpkg') | |||
</syntaxhighlight> | </syntaxhighlight> | ||
[[Catégorie:Tutoriel]] | [[Catégorie:Tutoriel]] |
Version du 17 avril 2023 à 15:31
À la demande d'une doctorante, j'ai rédigé ce petit bout de code en Javascript permettant d'intégrer une question de type Tracez un polygone sur la carte dans un questionnaire Limesurvey.
Ce code est à insérer dans l'énoncé d'une question de type texte long. La réponse sera générée automatiquement par Leaflet : il s'agira d'un geojson contenant le polygone tracé par l'utilisateur.
Version 1 - éditeur vectoriel classique
<!-- Leaflet -->
<link href="https://unpkg.com/leaflet@1.9.1/dist/leaflet.css" rel="stylesheet" />
<script src="https://unpkg.com/leaflet@1.9.1/dist/leaflet.js"></script>
<!-- Leaflet Draw -->
<link href="https://unpkg.com/leaflet-draw@1.0.4/dist/leaflet.draw.css" rel="stylesheet" />
<script src="https://unpkg.com/leaflet-draw@1.0.4/dist/leaflet.draw.js"></script>
<!-- Leaflet Search -->
<link href="https://unpkg.com/leaflet-search@3.0.3/dist/leaflet-search.src.css" rel="stylesheet" />
<script src="https://unpkg.com/leaflet-search@3.0.3/dist/leaflet-search.src.js"></script>
<!-- CSS pour la taille de la carte et pour cacher le formulaire de réponse -->
<style type="text/css">
#map {
height: 500px;
}
.answer-container {
display:none;
}
</style>
<!-- Question -->
Carte :
<div id="map"> </div>
<!-- JS de la carte -->
<script type="text/javascript" charset="utf-8">
// Paramètres de la carte de base
var map = L.map('map', {
crs: L.CRS.EPSG3857,
minZoom: 5,
maxZoom: 18,
}).setView([45.763, 4.732], 13);
// Ajout de la fonction de recherche
map.addControl(new L.Control.Search({
url: 'https://nominatim.openstreetmap.org/search?format=json&q={ s }',
jsonpParam: 'json_callback',
propertyName: 'display_name',
propertyLoc: ['lat', 'lon'],
marker: L.circleMarker([0, 0], { radius: 1 }),
autoCollapse: true,
autoType: false,
minLength: 2
}));
// Ajout de la couche WMS géoportail
var wmsGeoportail = L.tileLayer.wms('https://wxs.ign.fr/cartes/geoportail/r/wms?SERVICE=WMS&VERSION=1.3.0&CRS=EPSG:3857', {
layers: 'GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2',
attribution: 'IGN-F'
}).addTo(map);
// Définir une FeatureCollection pour les polygones tracés
var drawnItems = new L.FeatureGroup();
map.addLayer(drawnItems);
// Définir le style de la couche
var myStyle = {
"color": "#ff7800",
"weight": 5,
"opacity": 0.65
};
drawnItems.setStyle(myStyle);
// Paramètres de la barre d'outils d'édition
var drawControl = new L.Control.Draw({
draw: {
circle: false,
rectangle: false,
polyline: false,
marker: false
},
edit: {
featureGroup: drawnItems
}
});
map.addControl(drawControl);
// Evenements à déclencher lors de la création d'une entité
map.on(L.Draw.Event.CREATED, function (event) {
var layer = event.layer;
drawnItems.addLayer(layer);
var JSONoutput = JSON.stringify(drawnItems.toGeoJSON());
$('#answer{SGQ}').val(JSONoutput);
});
// Evenements à déclencher lors de la suppression d'une entité
map.on(L.Draw.Event.DELETED, function (event) {
var JSONoutput = JSON.stringify(drawnItems.toGeoJSON());
$('#answer{SGQ}').val(JSONoutput);
});
// Evenements à déclencher lors de l'édition d'une entité
map.on(L.Draw.Event.EDITED, function (event) {
var JSONoutput = JSON.stringify(drawnItems.toGeoJSON());
$('#answer{SGQ}').val(JSONoutput);
});
</script>
Version 2 - éditeur de type "pinceau à polygones"
<!-- Leaflet -->
<link href="https://unpkg.com/leaflet@1.9.1/dist/leaflet.css" rel="stylesheet" />
<script src="https://unpkg.com/leaflet@1.9.1/dist/leaflet.js"></script>
<!-- Leaflet Search -->
<link href="https://unpkg.com/leaflet-search@3.0.3/dist/leaflet-search.src.css" rel="stylesheet" />
<script src="https://unpkg.com/leaflet-search@3.0.3/dist/leaflet-search.src.js"></script>
<!-- Leaflet Paint-Polygon by Thibault Coupin -->
<script src="https://cdn.jsdelivr.net/npm/leaflet-paintpolygon@1.2.1-alpha.1/dist/Leaflet.PaintPolygon.min.js"></script>
<!-- CSS pour la taille de la carte et pour cacher le formulaire de réponse -->
<style type="text/css">
#map {
height: 500px;
}
.answer-container {
display:none;
}
</style>
<!-- Question -->
Carte :
<div id="map"> </div>
<!-- JS de la carte -->
<script type="text/javascript" charset="utf-8">
// Paramètres de la carte de base
var map = L.map('map', {
crs: L.CRS.EPSG3857,
minZoom: 5,
maxZoom: 18,
}).setView([45.763, 4.732], 13);
// Ajout de la fonction de recherche
map.addControl(new L.Control.Search({
url: 'https://nominatim.openstreetmap.org/search?format=json&q={ s }',
jsonpParam: 'json_callback',
propertyName: 'display_name',
propertyLoc: ['lat', 'lon'],
marker: L.circleMarker([0, 0], { radius: 1 }),
autoCollapse: true,
autoType: false,
minLength: 2
}));
// Ajout de la couche WMS géoportail
var wmsGeoportail = L.tileLayer.wms('https://wxs.ign.fr/cartes/geoportail/r/wms?SERVICE=WMS&VERSION=1.3.0&CRS=EPSG:3857', {
layers: 'GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2',
attribution: 'IGN-F'
}).addTo(map);
// Définir une FeatureCollection pour les polygones tracés
var drawnItems = new L.FeatureGroup();
map.addLayer(drawnItems);
// Définir le style de la couche
var myStyle = {
"color": "#ff7800",
"weight": 5,
"opacity": 0.65
};
drawnItems.setStyle(myStyle);
// Ajout du pinceau à polygones
var paintControl = L.control.paintPolygon({position: 'topleft'});
paintControl.addTo(map);
function updateDrawnItems(){
var JSONoutput = JSON.stringify(paintControl.getData());
$('#answer{SGQ}').val(JSONoutput);
}
setInterval('updateDrawnItems()', 1000); // Mise à jour des entités tracées toutes les secondes
</script>
Script R pour extraire les entités vectorielles des résultats LimeSurvey
library(dplyr)
library(sf)
library(geojsonsf)
# Lire les résultats de l'enquête
data = read.csv('./results-survey.csv') %>% as_tibble()
# Definir une fonction pour ajouter l'id limesurvey à une collection de géométries sf
add_id = function(sf, id) {
sf = sf %>% mutate(id_limesurvey = id)
return(sf)
}
######
### Dans toutes les lignes suivantes, remplacez "QUESTIONID" par le nom du champ contenant les géométries à extraire
######
geom_table = data %>%
filter(grepl("\"type\":\"FeatureCollection\"", QUESTIONID)) %>% # Filtrer les réponses où des géométries ont été saisies
select(QUESTIONID, id) %>%
mutate(sf = lapply(QUESTIONID, geojson_sf), # Convertir le geojson en objets sf
sf = mapply(add_id, sf, id, SIMPLIFY = FALSE)) # Appliquer la fonction add_id pour ajouter l'id_limesurvey
# Fusionner toutes les géométries dans un seul objet sf
geometries = bind_rows(geom_table$sf)
# Ecrire l'objet sf dans un geopackage
st_write(geometries, dsn = './QUESTIONID.gpkg')