190 lines
No EOL
5.7 KiB
JavaScript
190 lines
No EOL
5.7 KiB
JavaScript
import * as L from "./lib/leaflet/leaflet-src.esm.js"
|
|
import { MapSubFeature, PlaceDatabase } from "./places.js";
|
|
import "./lib/turf/turf.js"
|
|
|
|
let map = null;
|
|
/** @type {PlaceDatabase| null} */
|
|
let places = null;
|
|
|
|
export async function init(){
|
|
/** Le centre de la carte */
|
|
let map_center = null
|
|
/** Les bords de la carte */
|
|
let map_bounds = null
|
|
|
|
map = L.map(document.getElementById("map"), {
|
|
attributionControl: false,
|
|
zoomControl: false,
|
|
zoomSnap: 1,
|
|
zoomDelta: 1
|
|
})
|
|
|
|
{
|
|
let zoom_interval = null
|
|
function updateCssZoom(){
|
|
map.getContainer()
|
|
.style.setProperty("--zoom-level", map.getZoom())
|
|
}
|
|
map.addEventListener("zoom", updateCssZoom)
|
|
map.addEventListener("zoomstart", () => {
|
|
zoom_interval = setInterval(updateCssZoom, 50)
|
|
updateCssZoom()
|
|
})
|
|
map.addEventListener("zoomend", () => {
|
|
zoom_interval = clearInterval(zoom_interval)
|
|
updateCssZoom()
|
|
})
|
|
}
|
|
|
|
L.control.attribution({
|
|
position: 'topright'
|
|
}).addTo(map)
|
|
|
|
await Promise.all([
|
|
// Point définissant le centre de la carte
|
|
fetch("./couches/centre.geojson").then(res => res.json()).then(geojson => {
|
|
map_center = L.latLng([...geojson.features[0].geometry.coordinates].reverse())
|
|
console.log("Centre:", map_center)
|
|
}),
|
|
// Polygone définissant les limites de la carte
|
|
fetch("./couches/emprise.geojson").then(res => res.json()).then(geojson => {
|
|
let coordinate_list = geojson.features[0].geometry.coordinates[0]
|
|
let first_point = L.latLng([...coordinate_list[0]].reverse())
|
|
let bounds = L.latLngBounds(first_point, first_point)
|
|
for(let i = 1; i<coordinate_list.length; i++){
|
|
let point = [...coordinate_list[i]].reverse()
|
|
bounds.extend(point)
|
|
}
|
|
map_bounds = bounds
|
|
console.log("Bounds:", map_bounds)
|
|
}),
|
|
])
|
|
|
|
map.addEventListener("move", () => {
|
|
if(map_bounds.contains(map.getCenter())){
|
|
map.setMaxZoom(21)
|
|
} else {
|
|
map.setMaxZoom(18)
|
|
}
|
|
})
|
|
|
|
// La couche Openstreetmap standard
|
|
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
|
}).addTo(map)
|
|
|
|
// La couche custom de l'antenne
|
|
L.tileLayer('./tuiles/{z}/{x}/{y}.png', {
|
|
minZoom: 19,
|
|
maxZoom: 21
|
|
}).addTo(map)
|
|
|
|
L.marker(
|
|
map_center,
|
|
{
|
|
icon: L.divIcon({
|
|
html: `<img src="./logo.png" alt="Logo du camp interhack" />`,
|
|
className: "center-marker"
|
|
}),
|
|
title: "Camp Interhack 2026",
|
|
}
|
|
).addTo(map)
|
|
|
|
// Parametrage de la carte initiale
|
|
//map.setMaxBounds(map_bounds)
|
|
map.setView(map_center, 19, {
|
|
animate: false,
|
|
})
|
|
}
|
|
|
|
const HIGHLIGHT_LAYER = Symbol("Highlight map layer")
|
|
const AMENITY_MARKER_LAYER = Symbol("Amenity marker layer")
|
|
const PARENT_FEATURE = Symbol("Parent feature")
|
|
|
|
export async function init_places(places_db){
|
|
places = places_db
|
|
|
|
// La couche des zones disponibles
|
|
const area_highlight = L.geoJSON(null, {
|
|
pointToLayer: function(feature, latlng) {
|
|
let symbol = feature.mapSymbol;
|
|
if(symbol.markerUrl) {
|
|
|
|
let iconEl = document.createElement("img");
|
|
iconEl.src = symbol.markerUrl;
|
|
|
|
if(iconEl){
|
|
return L.marker(latlng, {
|
|
icon: L.divIcon({
|
|
className: "highlight-point-icon",
|
|
html: iconEl,
|
|
iconSize: [0, 0]
|
|
})
|
|
})
|
|
}
|
|
}
|
|
},
|
|
style: function(feature){
|
|
let symbol = feature.mapSymbol;
|
|
return {
|
|
className: "map-hilight-area",
|
|
fill: !!symbol.backgroundColor,
|
|
fillColor: symbol.backgroundColor,
|
|
fillOpacity: 0.5,
|
|
stroke: !!symbol.borderColor,
|
|
color: symbol.borderColor,
|
|
}
|
|
},
|
|
onEachFeature: function(feature, layer){
|
|
feature[HIGHLIGHT_LAYER] = layer
|
|
}
|
|
}).addTo(map)
|
|
|
|
// On ajoute toutes les zones à la carte
|
|
for(let [_feature_id, feature] of Object.entries(places.featuresById)){
|
|
area_highlight.addData(feature)
|
|
|
|
let point_feature = feature.asPoint()
|
|
if(point_feature !== feature){
|
|
area_highlight.addData(point_feature)
|
|
}
|
|
}
|
|
}
|
|
|
|
export function unhighlight_all(){
|
|
for(let el of document.querySelectorAll(".map-hilight-area.active")){
|
|
el.classList.remove("active")
|
|
}
|
|
for(let el of document.querySelectorAll(".highlight-point-icon.active")){
|
|
el.classList.remove("active")
|
|
}
|
|
}
|
|
|
|
export function highlight(place_or_placeid){
|
|
unhighlight_all()
|
|
|
|
let place;
|
|
|
|
if(typeof place_or_placeid == "string"){
|
|
place = places.getFeatureById(place_or_placeid)
|
|
} else {
|
|
place = place_or_placeid
|
|
}
|
|
|
|
if(place[HIGHLIGHT_LAYER]){
|
|
place[HIGHLIGHT_LAYER].getElement()
|
|
.classList.add("active")
|
|
}
|
|
|
|
let point_layer = place.asPoint()?.[HIGHLIGHT_LAYER];
|
|
if(point_layer && point_layer != place[HIGHLIGHT_LAYER]){
|
|
point_layer.getElement()
|
|
.classList.add("active")
|
|
}
|
|
|
|
let centroid = turf.centroid(place)
|
|
map.panTo(L.latLng(
|
|
centroid.geometry.coordinates[1],
|
|
centroid.geometry.coordinates[0]
|
|
))
|
|
} |