Nouveautés:
- AJAX pour récupérer les données depuis la base
- Leaflet pour l’API
- Openstreetmap pour les cartes
This commit is contained in:
2025-02-18 15:38:23 +01:00
parent cab19ef683
commit e627a8e3ff
26 changed files with 1409 additions and 157 deletions
+39
View File
@@ -0,0 +1,39 @@
.fullscreen-icon {
background-image: url('icon-fullscreen.svg');
background-size: 26px 52px;
}
.fullscreen-icon.leaflet-fullscreen-on {
background-position: 0 -26px;
}
.leaflet-touch .fullscreen-icon {
background-position: 2px 2px;
}
.leaflet-touch .fullscreen-icon.leaflet-fullscreen-on {
background-position: 2px -24px;
}
/* Safari still needs this vendor-prefix: https://caniuse.com/mdn-css_selectors_fullscreen */
/* stylelint-disable-next-line selector-no-vendor-prefix */
.leaflet-container:-webkit-full-screen {
width: 100% !important;
height: 100% !important;
z-index: 99999;
}
.leaflet-container:fullscreen {
width: 100% !important;
height: 100% !important;
z-index: 99999;
}
.leaflet-pseudo-fullscreen {
position: fixed !important;
width: 100% !important;
height: 100% !important;
top: 0 !important;
left: 0 !important;
z-index: 99999;
}
+284
View File
@@ -0,0 +1,284 @@
/*
* leaflet.fullscreen
* (c) Bruno B.; MIT License
* Uses fragments from the package 'screenfull'
*/
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// define an AMD module that requires 'leaflet'
// and resolve to an object containing leaflet
define('leafletFullScreen', ['leaflet'], factory);
} else if (typeof module === 'object' && module.exports) {
// define a CommonJS module that requires 'leaflet'
module.exports = factory(require('leaflet'));
} else {
// Assume 'leaflet' are loaded into global variable already
factory(root.L);
}
}(typeof self !== 'undefined'
? self
: this, (leaflet) => {
'use strict';
if (typeof document === 'undefined') {
console.warn('"window.document" is undefined; leaflet.fullscreen requires this object to access the DOM');
return false;
}
const nativeAPI = (() => {
const methodMap = [
// Standard
[
'requestFullscreen',
'exitFullscreen',
'fullscreenElement',
'fullscreenEnabled',
'fullscreenchange',
'fullscreenerror'
],
// New WebKit
[
'webkitRequestFullscreen',
'webkitExitFullscreen',
'webkitFullscreenElement',
'webkitFullscreenEnabled',
'webkitfullscreenchange',
'webkitfullscreenerror'
]
];
const baseList = methodMap[0];
const ret = {};
for (const methodList of methodMap) {
if (methodList[1] in document) {
for (let i = 0; i < methodList.length; i++) {
ret[baseList[i]] = methodList[i];
}
return ret;
}
}
return false;
})();
const eventNameMap = {
change: nativeAPI.fullscreenchange,
error: nativeAPI.fullscreenerror,
};
const fullscreenAPI = {
request(element, options) {
return new Promise((resolve, reject) => {
const onFullScreenEntered = function() {
this.off('change', onFullScreenEntered);
resolve();
}.bind(this);
this.on('change', onFullScreenEntered);
element = element || document.documentElement;
const returnPromise = element[nativeAPI.requestFullscreen](options);
if (returnPromise instanceof Promise) {
returnPromise.then(onFullScreenEntered).catch(reject);
}
});
},
exit() {
return new Promise((resolve, reject) => {
if (!this.isFullscreen) {
resolve();
return;
}
const onFullScreenExit = function() {
this.off('change', onFullScreenExit);
resolve();
}.bind(this);
this.on('change', onFullScreenExit);
const returnPromise = document[nativeAPI.exitFullscreen]();
if (returnPromise instanceof Promise) {
returnPromise.then(onFullScreenExit).catch(reject);
}
});
},
on(event, callback) {
const eventName = eventNameMap[event];
if (eventName) {
document.addEventListener(eventName, callback, false);
}
},
off(event, callback) {
const eventName = eventNameMap[event];
if (eventName) {
document.removeEventListener(eventName, callback, false);
}
},
nativeAPI: nativeAPI
};
Object.defineProperties(fullscreenAPI, {
isFullscreen: {
get() {
return Boolean(document[nativeAPI.fullscreenElement]);
}
},
isEnabled: {
enumerable: true,
get() {
// Coerce to boolean in case of old WebKit
return Boolean(document[nativeAPI.fullscreenEnabled]);
}
}
});
leaflet.Control.FullScreen = leaflet.Control.extend({
options: {
position: 'topleft',
title: 'Full Screen',
titleCancel: 'Exit Full Screen',
forceSeparateButton: false,
forcePseudoFullscreen: false,
fullscreenElement: false
},
_screenfull: fullscreenAPI,
onAdd(map) {
let className = 'leaflet-control-zoom-fullscreen';
let container;
let content = '';
if (map.zoomControl && !this.options.forceSeparateButton) {
container = map.zoomControl._container;
} else {
container = leaflet.DomUtil.create('div', 'leaflet-bar');
}
if (this.options.content) {
content = this.options.content;
} else {
className += ' fullscreen-icon';
}
this._createButton(this.options.title, className, content, container, this.toggleFullScreen, this);
this._map.fullscreenControl = this;
this._map.on('enterFullscreen exitFullscreen', this._toggleState, this);
return container;
},
onRemove() {
leaflet.DomEvent
.off(this.link, 'click', leaflet.DomEvent.stop)
.off(this.link, 'click', this.toggleFullScreen, this);
if (this._screenfull.isEnabled) {
leaflet.DomEvent
.off(this._container, this._screenfull.nativeAPI.fullscreenchange, leaflet.DomEvent.stop)
.off(this._container, this._screenfull.nativeAPI.fullscreenchange, this._handleFullscreenChange, this);
leaflet.DomEvent
.off(document, this._screenfull.nativeAPI.fullscreenchange, leaflet.DomEvent.stop)
.off(document, this._screenfull.nativeAPI.fullscreenchange, this._handleFullscreenChange, this);
}
},
_createButton(title, className, content, container, fn, context) {
this.link = leaflet.DomUtil.create('a', className, container);
this.link.href = '#';
this.link.title = title;
this.link.innerHTML = content;
this.link.setAttribute('role', 'button');
this.link.setAttribute('aria-label', title);
L.DomEvent.disableClickPropagation(container);
leaflet.DomEvent
.on(this.link, 'click', leaflet.DomEvent.stop)
.on(this.link, 'click', fn, context);
if (this._screenfull.isEnabled) {
leaflet.DomEvent
.on(container, this._screenfull.nativeAPI.fullscreenchange, leaflet.DomEvent.stop)
.on(container, this._screenfull.nativeAPI.fullscreenchange, this._handleFullscreenChange, context);
leaflet.DomEvent
.on(document, this._screenfull.nativeAPI.fullscreenchange, leaflet.DomEvent.stop)
.on(document, this._screenfull.nativeAPI.fullscreenchange, this._handleFullscreenChange, context);
}
return this.link;
},
toggleFullScreen() {
const map = this._map;
map._exitFired = false;
if (map._isFullscreen) {
if (this._screenfull.isEnabled && !this.options.forcePseudoFullscreen) {
this._screenfull.exit().then(() => map.invalidateSize());
} else {
leaflet.DomUtil.removeClass(this.options.fullscreenElement
? this.options.fullscreenElement
: map._container, 'leaflet-pseudo-fullscreen');
map.invalidateSize();
}
map.fire('exitFullscreen');
map._exitFired = true;
map._isFullscreen = false;
} else {
if (this._screenfull.isEnabled && !this.options.forcePseudoFullscreen) {
this._screenfull.request(this.options.fullscreenElement
? this.options.fullscreenElement
: map._container).then(() => map.invalidateSize());
} else {
leaflet.DomUtil.addClass(this.options.fullscreenElement
? this.options.fullscreenElement
: map._container, 'leaflet-pseudo-fullscreen');
map.invalidateSize();
}
map.fire('enterFullscreen');
map._isFullscreen = true;
}
},
_toggleState() {
this.link.title = this._map._isFullscreen
? this.options.title
: this.options.titleCancel;
this._map._isFullscreen
? L.DomUtil.removeClass(this.link, 'leaflet-fullscreen-on')
: L.DomUtil.addClass(this.link, 'leaflet-fullscreen-on');
},
_handleFullscreenChange(ev) {
const map = this._map;
if (ev.target === map.getContainer() && !this._screenfull.isFullscreen && !map._exitFired) {
this._screenfull.exit().then(() => map.invalidateSize());
map.fire('exitFullscreen');
map._exitFired = true;
map._isFullscreen = false;
}
}
});
leaflet.Map.include({
toggleFullscreen() {
this.fullscreenControl.toggleFullScreen();
}
});
leaflet.Map.addInitHook(function() {
if (this.options.fullscreenControl) {
this.addControl(leaflet.control.fullscreen(this.options.fullscreenControlOptions));
}
});
leaflet.control.fullscreen = function(options) {
return new leaflet.Control.FullScreen(options);
};
return { leaflet };
}));
+1
View File
@@ -0,0 +1 @@
<svg viewBox="0 0 26 52" xmlns="http://www.w3.org/2000/svg"><path d="M20.6 36.7H16a.9.9 0 0 1-.8-.8v-4.5c0-.2.2-.4.4-.4h1.4c.3 0 .5.2.5.4v3h3c.2 0 .4.2.4.5v1.4c0 .2-.2.4-.4.4zm-9.9-.8v-4.5c0-.2-.2-.4-.4-.4H8.9c-.3 0-.5.2-.5.4v3h-3c-.2 0-.4.2-.4.5v1.4c0 .2.2.4.4.4H9.9c.4 0 .8-.4.8-.8zm0 10.7V42c0-.4-.4-.8-.8-.8H5.4c-.2 0-.4.2-.4.4v1.4c0 .3.2.5.4.5h3v3c0 .2.2.4.5.4h1.4c.2 0 .4-.2.4-.4zm6.9 0v-3h3c.2 0 .4-.2.4-.5v-1.4c0-.2-.2-.4-.4-.4H16c-.4 0-.8.4-.8.8v4.5c0 .2.2.4.4.4h1.5c.3 0 .5-.2.5-.4zM5 10.3V5.9c0-.5.4-.9.9-.9h4.4c.2 0 .4.2.4.4V7c0 .2-.2.4-.4.4h-3v3c0 .2-.2.4-.4.4H5.4a.4.4 0 0 1-.4-.4zm10.3-4.9V7c0 .2.2.4.4.4h3v3c0 .2.2.4.4.4h1.5c.2 0 .4-.2.4-.4V5.9c0-.5-.4-.9-.9-.9h-4.4c-.2 0-.4.2-.4.4zm5.3 9.9H19c-.2 0-.4.2-.4.4v3h-3c-.2 0-.4.2-.4.4v1.5c0 .2.2.4.4.4h4.4c.5 0 .9-.4.9-.9v-4.4c0-.2-.2-.4-.4-.4zm-9.9 5.3V19c0-.2-.2-.4-.4-.4h-3v-3c0-.2-.2-.4-.4-.4H5.4c-.2 0-.4.2-.4.4v4.4c0 .5.4.9.9.9h4.4c.2 0 .4-.2.4-.4z" fill="currentColor"/></svg>

After

Width:  |  Height:  |  Size: 947 B

File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+99
View File
@@ -0,0 +1,99 @@
// On déclare les coordonnées de Paris
//let lat = 48.852969;
//let long = 2.349903;
// On déclare les coordonnées de Dijon
let lat = 47.316669;
let long = 5.01667;
let limites = [];
let markers = L.markerClusterGroup();
let map = L.map("map", {
zoom: 13,
center: [lat, long]
});
L.tileLayer("https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png", {
minZoom: 1,
maxZoom: 20,
attribution: 'données © <a href="//osm.org/copyright">OpenStreetMap</a>/ODbL - rendu <a href="//openstreetmap.fr">OSM France</a>'
}).addTo(map);
// On charge sites.json
fetch("/maps/api/liste.php")
.then(data => data.json())
.then(sites => {
// On boucle sur les sites
for(let site of sites){
let coords = [site.lat, site.long];
// On charge l'icône du marqueur
let icone = L.icon({
iconUrl: "/maps/images/poi.png",
iconSize: [41,41],
iconAnchor: [12.5, 41],
popupAnchor: [0, -41]
/*
iconUrl: "/maps/images/pin.png",
iconSize: [25,41],
*/
});
// On crée le marqueur pour chaque site
let marker = L.marker(coords, {
icon: icone
});
/*
$lightbox['title_thumb'] = $title_thumb;
$lightbox['exif'] = $exif;
$lightbox['title'] = $x;
$lightbox['legende'] = $y;
$lightbox['thumb'] = $thumb;
$lightbox['big'] = $big;
$lightbox['keywords'] = $keywords;
$lightbox['creator'] = $creator;
$lightbox['gps'] = $gps;
$lightbox['lat'] = $latitude;
$lightbox['long'] = $longitude;
$lightbox['description'] = $description;
$lightbox['width'] = $width;
$lightbox['height'] = $height;
<img src="${site.thumb}" alt="${site.filename}" width="300" height="300">
<img src="${site.thumb}" alt="${site.filename}" width="`+largeur+`" height="`+hauteur+`">
*/
if ( parseInt(site.width) <= parseInt(site.height) ) {
largeur = 200;
hauteur = 300;
}
else
{
largeur = 300;
hauteur = 200;
}
let popup = `<div class="popup">
<div>
<a href="${site.big}" title="${site.title_thumb}" data-lcl-txt="${site.description}" data-lcl-author="${site.creator}">
<img src="${site.thumb}" alt="${site.filename}" width="`+largeur+`" height="`+hauteur+`">
</a>
<h2>${site.title_thumb}</h2>
<p>${site.exif}</p>
</div>
</div>`;
marker.bindPopup(popup);
limites.push(coords);
// On ajoute le marqueur au cluster
markers.addLayer(marker);
}
// On ajoute les clusters à la carte
map.addLayer(markers);
map.fitBounds(limites);
});