scripts/osm-local-groups-bubbles/index.html

782 lines
33 KiB
HTML
Raw Normal View History

2023-06-13 15:33:47 +02:00
<!DOCTYPE html>
<html>
<head>
<title>Groupes locaux OSM Fr</title>
<meta charset="utf-8"/>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"/>
<!-- Styles -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fork-awesome@1.2.0/css/fork-awesome.min.css"
integrity="sha256-XoaMnoYC5TH6/+ihMEnospgm0J1PM/nioxbOUdnM8HY=" crossorigin="anonymous">
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: relative;
top: 0;
bottom: 0;
width: 100%;
height: 500px;
border: solid 3px
}
</style>
<!-- Chart code -->
<!-- <script src='geojson.json'></script>-->
<script src='https://unpkg.com/maplibre-gl@3.0.1/dist/maplibre-gl.js'></script>
<link href='https://unpkg.com/maplibre-gl@3.0.1/dist/maplibre-gl.css' rel='stylesheet'/>
<script type="module">
// geojson made with csv imported in https://www.convertcsv.com/csv-to-geojson.htm
// import * as geojsonData from "./geojson.json"
// source umap des groupes locaux osm
// http://umap.openstreetmap.fr/fr/datalayer/781918/
window.addEventListener("load", async (event) => {
console.log('dom loaded')
// let geojsonData = await fetch('./geojsonData.json').then((response) => response)
let geojsonData = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-1.56352,
47.22133
]
},
"properties": {
"id": 1,
"Groupe": "Nantes",
"Lieu": "Association Médiagraph",
"Periodicite": "2ème jeudi du mois",
"Web": "http://nantes.openstreetmap.fr",
"Adresse": "1 rue d'Auvours",
"CP": 44000,
"Ville": "Nantes",
"User": "naomap",
"Descriptif": "Ateliers thématiques pour échanger et monter en compétence. Présence à des événements tels la Fête de la Science. Organisation de cartoparties."
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-1.68239,
48.11715
]
},
"properties": {
"id": 2,
"Groupe": "Rennes",
"Lieu": "Local de l'asso \"Et si on se parlait ?\"",
"Periodicite": "2ème lundi du mois",
"Web": "https://wiki.openstreetmap.org/wiki/Rennes",
"Adresse": "19 Rue Legraverend",
"CP": 35000,
"Ville": "Rennes",
"User": "PanierAvide",
"Descriptif": "Groupe des contributeurs OSM d'Ille-et-Vilaine"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
5.11297,
47.3124
]
},
"properties": {
"id": 3,
"Groupe": "Dijon",
"Lieu": "Association COAGUL et fablab LAB6",
"Periodicite": "tous les mardis",
"Web": "https://wiki.openstreetmap.org/wiki/Dijon",
"Adresse": "3 rue des prairies",
"CP": 21800,
"Ville": "Quetigny",
"User": "Dlareg",
"Descriptif": "Groupe local porté logistiquement par l'association COAGUL"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
4.86094,
45.76379
]
},
"properties": {
"id": 4,
"Groupe": "Lyon",
"Lieu": "Tubà (Tube à expérimentations urbaines)",
"Periodicite": "3ème mardi du mois",
"Web": "http://wiki.openstreetmap.org/wiki/FR:Lyon#Groupe_local_lyonnais",
"Adresse": "227 cours Lafayette",
"CP": 69006,
"Ville": "Lyon",
"User": "renecha",
"Descriptif": "Groupe informel. Collaborations avec CartONG. Animation d'ateliers de formation à la Maison pour Tous (Salle des Rancy). Participation au salon Primevère et aux JDLL..."
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
5.37301,
43.29206
]
},
"properties": {
"id": 5,
"Groupe": "Marseille",
"Lieu": "La Boate",
"Periodicite": "1er lundi du mois",
"Web": "https://wiki.openstreetmap.org/wiki/Marseille",
"Adresse": "35 rue de la paix marcel paul",
"CP": 13001,
"Ville": "Marseille",
"User": "",
"Descriptif": ""
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
5.70509,
45.18761
]
},
"properties": {
"id": 6,
"Groupe": "Grenoble",
"Lieu": "La Turbine.coop",
"Periodicite": "un lundi par mois",
"Web": "https://wiki.openstreetmap.org/wiki/Grenoble_groupe_local",
"Adresse": "3-5 esplanade Andry Farcy",
"CP": 38000,
"Ville": "Grenoble",
"User": "Gall",
"Descriptif": "Partenariat avec la Turbine.coop (communication) https://turbine.coop/"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
3.8980838,
43.6030127
]
},
"properties": {
"id": 7,
"Groupe": "Montpellier",
"Lieu": "Atelier des Pigistes",
"Periodicite": "Le dernier mercredi du mois",
"Web": "https://wiki.openstreetmap.org/wiki/Hérault#Communauté<https://wiki.openstreetmap.org/wiki/Hérault#Communauté>",
"Adresse": "171, rue Frimaire, 34000 Montpellier",
"CP": 34000,
"Ville": "Montpellier",
"User": "Ptigrouick",
"Descriptif": "Dans le cadre des rendez-vous du GULL local (https://montpellibre.fr/spip.php?rubrique103), Envoyez un courriel d'inscription 2-3j avant pour vous assurer que des contributeurs seront aussi présents (c'est très très généralement le cas, mais on ne sait jamais :-) Nous organisons environ une vingtaine d'ateliers/cartoparties/mapathons par an, soit seuls, soit en relation avec le GULL de Montpellier. Page OpenStreetMap https://wiki.openstreetmap.org/wiki/HA13%A9rault#CommunautA13%A9%3C%3Ca%20target= page dédiée : https://herosm.fr/"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
0.33965,
46.58151
]
},
"properties": {
"id": 8,
"Groupe": "Poitiers",
"Lieu": "CRIJ",
"Periodicite": "1ᵉʳ jeudi du mois",
"Web": "https://wiki.openstreetmap.org/wiki/Poitiers/Coordination",
"Adresse": "64 rue Léon Gambetta",
"CP": 86000,
"Ville": "Poitiers",
"User": "frem-eu",
"Descriptif": ""
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
6.16771,
48.66731
]
},
"properties": {
"id": 9,
"Groupe": "Nancy",
"Lieu": "Fabrique des possibles",
"Periodicite": "le 4ème mercredi de chaque mois",
"Web": "http://nancy.osmfr.org",
"Adresse": "164, avenue du Général Leclerc",
"CP": 54500,
"Ville": "Vandoeuvre-lès-Nancy",
"User": "Rom1",
"Descriptif": "Convention signée avec la Fabrique Collective de la Culture du Libre (FCCL), structure créée par la mairie de Vandoeuvre-lès-Nancy. Les échanges et annonces sont jusquà présents faits sur lhttps://forum.openstreetmap.fr/c/groupes-locaux/nancy/55"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-52.27313,
4.90387
]
},
"properties": {
"id": 10,
"Groupe": "Guyane",
"Lieu": "Parc Amazonien de Guyane",
"Periodicite": "Dernier mardi du mois",
"Web": "https://fr.osm.social/@osm_gf",
"Adresse": "1 Rue Lederson",
"CP": 97300,
"Ville": "Rémire-Montjoly",
"User": "adrienandrem",
"Descriptif": "Pour vous joindre à la réunion mensuelle, envoyez-nous un message à local-guyane@listes.openstreetmap.fr ou osm-gf@laposte.net. Début des rencontres vers 18:30."
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
55.536384,
-21.115
]
},
"properties": {
"id": 11,
"Groupe": "La Réunion",
"Lieu": "SEAS-OI",
"Periodicite": "Premier vendredi du mois",
"Web": "https://www.facebook.com/openstreetmapreunion/",
"Adresse": "40 avenue de Soweto",
"CP": 97410,
"Ville": "Saint-Pierre",
"User": "arnaud_mapali",
"Descriptif": "Cartoparties, action sur Hot OSM"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-0.5725,
44.85037
]
},
"properties": {
"id": 12,
"Groupe": "Bordeaux",
"Lieu": "La Mézannine, association Aquilenet",
"Periodicite": "2ème lundi du mois",
"Web": "https://wiki.openstreetmap.org/wiki/Bordeaux#Groupe_Local",
"Adresse": "20 rue Tourat",
"CP": 33000,
"Ville": "Bordeaux",
"User": "vinber",
"Descriptif": ""
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
6.236,
44.0928
]
},
"properties": {
"id": 13,
"Groupe": "Digne-les-bains",
"Lieu": "Xsalto",
"Periodicite": "irrégulière pour le moment, les rencontres sont annoncées sur http://www.linux-alpes.org",
"Web": "https://wiki.openstreetmap.org/wiki/Digne-les-Bains#Groupe_OSM_local",
"Adresse": "33 allée des Fontainiers",
"CP": 4000,
"Ville": "33 allée des Fontainiers",
"User": "Arnaud Champollion",
"Descriptif": "Groupe animé par l'association Linux-Alpes, les réunions sont hébergées chez Xsalto, liste de discussion liste osmdigne@linux-alpes.org"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
2.8953121,
42.6985304
]
},
"properties": {
"id": 14,
"Groupe": "Perpignan",
"Lieu": "",
"Periodicite": "",
"Web": "https://wiki.openstreetmap.org/wiki/France:Pyrénées-Orientales",
"Adresse": "",
"CP": null,
"Ville": "",
"User": "LySioS",
"Descriptif": "Mise en relation des contributeurs sur canal de discussion via telegram https://t.me/osm66cat ou matrix https://matrix.to/#/!xEPNuwBdujUBHXKDIs:matrix.org"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
2.1252812,
48.6242451
]
},
"properties": {
"id": 15,
"Groupe": "Ile de France / Essonne",
"Lieu": "Briis-sous-Forges",
"Periodicite": "1er mardi du mois",
"Web": "",
"Adresse": "Le Pilo, Briis sous forges",
"CP": 91640,
"Ville": "Briis-sous-Forges",
"User": "tykayn",
"Descriptif": ""
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
2.3204584,
48.8153535
]
},
"properties": {
"id": 16,
"Groupe": "Ile de France / Essonne",
"Lieu": "Paris Sud - Montrouge",
"Periodicite": "2e jeudi du mois",
"Web": "",
"Adresse": "Le Schmilblick, Montrouge",
"CP": 92120,
"Ville": "Montrouge",
"User": "Overflorian",
"Descriptif": ""
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
1.44301,
43.60175
]
},
"properties": {
"id": 17,
"Groupe": "Toulouse",
"Lieu": "Artilect FabLab Toulouse",
"Periodicite": "3e samedi du mois",
"Web": "https://wiki.openstreetmap.org/wiki/FR:Toulouse",
"Adresse": "10 rue Tripière",
"CP": 31000,
"Ville": "Toulouse",
"User": "orhygine",
"Descriptif": "Les contributeurs OpenStreetMap de la région se réunissent tous les troisièmes samedis du mois. Toute personne intéressée de près ou de loin par OpenStreetMap est bienvenue pour se joindre au groupe. Les débutants pourront obtenir des conseils pour les aider à mettre le pied à l'étrier et les contributeurs expérimentés pourront échanger leurs trucs et astuces de cartographe."
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-1.4701,
43.4933
]
},
"properties": {
"id": 18,
"Groupe": "Pays basque - Sud Landes",
"Lieu": "Bayonne et alentours",
"Periodicite": "tous les 2 mois environ",
"Web": "https://wiki.openstreetmap.org/wiki/Pays_basque_Sud_Landes",
"Adresse": "",
"CP": null,
"Ville": "",
"User": "Patchanka",
"Descriptif": ""
}
}
]
}
console.log('maplibregl', maplibregl)
var map = new maplibregl.Map({
container: 'map',
style:
2023-06-14 13:27:48 +02:00
'https://api.maptiler.com/maps/streets/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL',
2023-06-13 15:33:47 +02:00
center: [0, 0],
zoom: 1,
});
map.on('load', function () {
2023-06-14 13:27:48 +02:00
map.addSource('local_osm_groups', {
2023-06-13 15:33:47 +02:00
type: 'geojson',
data: geojsonData,
cluster: false,
2023-06-13 15:33:47 +02:00
clusterMaxZoom: 14, // Max zoom to cluster points on
clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)
});
map.addLayer({
id: 'clusters',
type: 'marker',
2023-06-14 13:27:48 +02:00
source: 'local_osm_groups',
2023-06-13 15:33:47 +02:00
// filter: ['has', 'point_count'],
paint: {
// Use step expressions (https://maplibre.org/maplibre-style-spec/#expressions-step)
// with three steps to implement three types of circles:
// * Blue, 20px circles when point count is less than 100
// * Yellow, 30px circles when point count is between 100 and 750
// * Pink, 40px circles when point count is greater than or equal to 750
'circle-color': [
'step',
['get', 'point_count'],
2023-06-14 13:27:48 +02:00
'#ff1818',
2023-06-13 15:33:47 +02:00
1,
2023-06-14 13:27:48 +02:00
'#f1ab75',
2023-06-13 15:46:50 +02:00
40,
2023-06-14 13:27:48 +02:00
'#ffadcb'
2023-06-13 15:33:47 +02:00
],
'circle-radius': [
'step',
['get', 'point_count'],
50,
60,
80,
120,
100
]
}
});
map.addLayer({
id: 'cluster-count',
type: 'symbol',
2023-06-14 13:27:48 +02:00
source: 'local_osm_groups',
2023-06-13 15:33:47 +02:00
filter: ['has', 'point_count'],
layout: {
'text-field': '{point_count_abbreviated}',
'text-font': ['DIN Offc Pro Medium', 'Arial Unicode MS Bold'],
'text-size': 12
}
});
map.addLayer({
id: 'unclustered-point',
type: 'circle',
2023-06-14 13:27:48 +02:00
source: 'local_osm_groups',
2023-06-13 15:33:47 +02:00
filter: ['!', ['has', 'point_count']],
paint: {
'circle-color': '#11b4da',
'circle-radius': 4,
'circle-stroke-width': 1,
'circle-stroke-color': '#fff'
}
});
// inspect a cluster on click
map.on('click', 'clusters', function (e) {
var features = map.queryRenderedFeatures(e.point, {
layers: ['clusters']
});
var clusterId = features[0].properties.cluster_id;
2023-06-14 13:27:48 +02:00
map.getSource('local_osm_groups').getClusterExpansionZoom(
2023-06-13 15:33:47 +02:00
clusterId,
function (err, zoom) {
if (err) return;
map.easeTo({
center: features[0].geometry.coordinates,
zoom: zoom
});
}
);
});
// When a click event occurs on a feature in
// the unclustered-point layer, open a popup at
// the location of the feature, with
// description HTML from its properties.
map.on('click', 'unclustered-point', function (e) {
var coordinates = e.features[0].geometry.coordinates.slice();
var Groupe = e.features[0].properties.Groupe;
2023-06-13 15:46:50 +02:00
var Descriptif = e.features[0].properties.Descriptif;
2023-06-13 15:33:47 +02:00
var mag = e.features[0].properties.Periodicite;
var addr = e.features[0].properties.Adresse;
var cp = e.features[0].properties.CP;
var ville = e.features[0].properties.Ville;
var website = e.features[0].properties.Web;
// Ensure that if the map is zoomed out such that
// multiple copies of the feature are visible, the
// popup appears over the copy being pointed to.
2023-06-13 15:46:50 +02:00
console.log('e.lngLat', e.lngLat , e)
2023-06-13 15:33:47 +02:00
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
}
2023-06-14 13:27:48 +02:00
console.log('coordinates', coordinates)
2023-06-13 15:33:47 +02:00
new maplibregl.Popup()
.setLngLat(coordinates)
.setHTML(
2023-06-13 15:46:50 +02:00
` <h1>⛯${Groupe}</h1><br>🗓️🗓️ rencontres: ${mag}<br> ${addr}, ${cp}, ${ville}
<br> <a href="${website}">🌐 ${website}</a>
<br> <a href="${e.features[0].properties.User}">👤👤 👤${e.features[0].properties.User}</a>
<hr>
<br> <blockquote>${Descriptif}</blockquote>
`
2023-06-13 15:33:47 +02:00
)
.addTo(map);
});
map.on('mouseenter', 'clusters', function () {
map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', 'clusters', function () {
map.getCanvas().style.cursor = '';
});
2023-06-14 13:27:48 +02:00
map.on('mousemove', function (e) {
var features = map.queryRenderedFeatures(e.point);
// Limit the number of properties we're displaying for
// legibility and performance
var displayProperties = [
'type',
'properties',
'id',
'layer',
'source',
'sourceLayer',
'state'
];
var displayFeatures = features.map(function (feat) {
var displayFeat = {};
displayProperties.forEach(function (prop) {
displayFeat[prop] = feat[prop];
});
return displayFeat;
});
document.getElementById('features').innerHTML = JSON.stringify(
displayFeatures,
null,
2
);
});
var size = 50;
// implementation of StyleImageInterface to draw a pulsing dot icon on the map
// see https://maplibre.org/maplibre-gl-js-docs/api/properties/#styleimageinterface for more info
var pulsingDot = {
width: size,
height: size,
data: new Uint8Array(size * size * 4),
// get rendering context for the map canvas when layer is added to the map
onAdd: function () {
var canvas = document.createElement('canvas');
canvas.width = this.width;
canvas.height = this.height;
this.context = canvas.getContext('2d');
},
// called once before every frame where the icon will be used
render: function () {
var duration = 1000;
var t = (performance.now() % duration) / duration;
var radius = (size / 2) * 0.3;
var outerRadius = (size / 2) * 0.7 * t + radius;
var context = this.context;
// draw outer circle
context.clearRect(0, 0, this.width, this.height);
context.beginPath();
context.arc(
this.width / 2,
this.height / 2,
outerRadius,
0,
Math.PI * 2
);
context.fillStyle = 'rgba(255, 200, 200,' + (1 - t) + ')';
context.fill();
// draw inner circle
context.beginPath();
context.arc(
this.width / 2,
this.height / 2,
radius,
0,
Math.PI * 2
);
context.fillStyle = 'rgba(255, 100, 100, 1)';
context.strokeStyle = 'white';
context.lineWidth = 2 + 4 * (1 - t);
context.fill();
context.stroke();
// update this image's data with data from the canvas
this.data = context.getImageData(
0,
0,
this.width,
this.height
).data;
// continuously repaint the map, resulting in the smooth animation of the dot
map.triggerRepaint();
// return `true` to let the map know that the image was updated
return true;
}
};
map.addImage('pulsing-dot', pulsingDot, { pixelRatio: 2 });
map.addLayer({
'id': 'points',
'type': 'symbol',
'source': 'local_osm_groups',
'layout': {
'icon-image': 'pulsing-dot'
}
});
map.addLayer({
'id': 'poi-labels',
'type': 'symbol',
'source': 'local_osm_groups',
'layout': {
'text-field': ['get', 'Groupe'],
'text-variable-anchor': ['top', 'bottom', 'left', 'right'],
'text-radial-offset': 0.5,
'text-justify': 'auto',
'icon-image': ['concat', ['get', 'icon'], '_15']
}
});
2023-06-13 15:33:47 +02:00
});
})
</script>
</head>
<body>
<div class="container">
<article class="content">
<h1 class="title is-1">Groupes locaux OSM Fr</h1>
<div id="map">
</div>
<p>
<ul>
<li>
Sur le wiki OSM: <br>
<a href="https://framacalc.org/osm-groupes-locaux">
Framacalc: Liste des groupes locaux se réunissant régulièrement
</a>
<br>
<a href="https://umap.openstreetmap.fr/fr/map/groupes-locaux-openstreetmap_152488">
Carte des groupes locaux se réunissant régulièrement
</a>
</li>
<li>
<a href="https://umap.openstreetmap.fr/fr/map/groupes-locaux-openstreetmap_152488#6/46.392/1.714">
carte umap
</a>
</li>
</ul>
</p>
</article>
</div>
<footer class="footer">
<div class="container">
<div class="content has-text-centered">
<p>
<a href="https://www.cipherbliss.com">
<img src="https://www.cipherbliss.com/wp-content/uploads/2016/12/rond.png"
class="vdn-page-primary-navigation-site-logo custom-logo"
alt="Cipher Bliss" width="150" height="162"> CipherBliss
</a>
<br>
The source code is licensed
AGPLv3+.
<br>
The website content is licensed <a href="http://creativecommons.org/licenses/by-sa/4.0/">CC BY SA
4.0</a>.
</p>
</div>
</div>
</footer>
</body>
</html>