WIP: test interactive wall layers

This commit is contained in:
2026-09-14 16:00:23 +02:00
parent 7293ac348d
commit ace42261cf
9 changed files with 210 additions and 82 deletions
+102 -29
View File
@@ -40,15 +40,8 @@ export const INIT_ZOOM = 14;
*/
function capitalize(text) {
let capital = text;
if (text) {
let words = text.split(' ');
capital = '';
for (let w of words) {
w = w[0].toUpperCase() + w.slice(1);
capital += w + ' ';
}
capital.trimEnd();
if (text !== null && text !== undefined && text.at && text.length) {
capital = text.at(0).toLocaleUpperCase() + text.slice(1);
}
return capital;
@@ -62,6 +55,7 @@ GIS.initMap = async function (mapId, zoomLevel = this.INIT_ZOOM) {
let map = L.map(mapId, {
//attributionControl: false,
minZoom: GIS.MIN_ZOOM,
maxZoom: GIS.MAX_ZOOM,
}).setView(this.CENTER_COORDS, zoomLevel);
map.crs = L.CRS.EPSG4326;
@@ -102,15 +96,80 @@ GIS.initMap = async function (mapId, zoomLevel = this.INIT_ZOOM) {
};
L.control.layers(baseMap, cartography).addTo(map);
// TEST: marker with SVG icon...
L.marker([40.5591380,14.2296069], { icon: Icons.wall, id: 'tiberio' })
.on('click', () => this.activateBuildingView('tiberio'))
.bindTooltip('Mappa USM')
.addTo(map);
GisState.map = map;
GisState.cartography.buildings = buildings;
return map;
}
/**
* Draft implementation to activate
* a dedicated view with details
* to navigate building walls
* @todo Find better name
* @param {string} layerId
*/
GIS.activateBuildingView = async function(layerId) {
const map = GisState.map;
map.setMinZoom(19);
map.setMaxZoom(25);
/**
* @type {L.GeoJSON} currentGeometry
*/
let currentGeometry = {};
map.removeLayer(GisState.baseLayers['OpenStreetMap']);
// Remove site layers then re-add it so vector lines
// are placed correctly above the new base map
GisState.layers.geometries.removeFrom(map);
map.addLayer(GisState.baseLayers['Limiti amministrativi']);
GisState.cartography.buildings.addTo(map);
GisState.layers.geometries.addTo(map);
GisState.layers.geometries.eachLayer(l => {
if (l.options.id === layerId) {
currentGeometry = l;
return;
}
});
const center = currentGeometry.getBounds().getCenter();
// TODO: Use DB to handle these?
const wallTechniques = [
'reticolata',
'incerta',
'mista',
'laterizia',
'cementizia',
'poligonale',
];
// TODO: create color lookup table...
const wallLayer = await this.loadGeoJSON(
`murarie/${layerId}/reticolata.geojson`,
Options.walls,
true
);
wallLayer.addTo(map);
map.setView(wallLayer.getBounds().getCenter(), 20);
// This is terrible...
UI.addBuildingViewBar();
map._container.classList.add('bview-border');
}
/**
* Fetches references to cartography layers
* and updates GisState
*/
GIS.fetchCartographyLayers = async function () {
GIS.fetchCartographyLayers = async function() {
const data = await this._fetchData('geoimages/menu')
.catch(error => console.error(`Could not fetch data for geo images: ${error}`));
@@ -187,6 +246,9 @@ GIS.addLayerGroups = async function (map) {
sites.markers.addTo(map);
sites.geom.addTo(map);
// A layer group with all site geometries (GeoJSON)
GisState.layers.geometries = sites.geom;
const groups = await Promise.all(
[
this.notConserved(),
@@ -213,7 +275,7 @@ GIS.sites = async function () {
if (record.geojson) {
const options = record.gisId === 'grotta_azzurra' ?
Options.grotta : Options.site;
geom.push(await this.loadSiteLayer(record, options));
geom.push(await this.loadSiteLayer(record, options, false));
}
if (record.area) {
const options = record.gisId === 'villa_bismarck' ?
@@ -412,7 +474,6 @@ GIS.reuse = async function () {
* @returns {{baseMap: {"OpenStreetMap": L.TileLayer}}}
*/
GIS.initLayers = async function(map) {
let osmap = new L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxNativeZoom : GIS.MAX_ZOOM,
maxZoom: GIS.MAX_ZOOM,
@@ -437,6 +498,8 @@ GIS.initLayers = async function(map) {
'Limiti amministrativi' : boundaries,
};
GisState.baseLayers = baseMap;
return baseMap;
}
/**
@@ -488,7 +551,7 @@ GIS.toggleSpherical = async function(map) {
* @param {string} geoJSON geoJSON filename
* @param {{color, opacity, weight, fillColor, fillOpacity}} options Style options for features
* @param {boolean} popup Should the features have a popup?
* @returns {L.Layer}
* @returns {L.GeoJSON}
*/
GIS.loadGeoJSON = async function (geoJSON, options, popup = true) {
const geo = await fetch(`${BASE_URL}/geojson/${geoJSON}`)
@@ -496,6 +559,9 @@ GIS.loadGeoJSON = async function (geoJSON, options, popup = true) {
.catch(error => console.error(`Can't load layer ${geoJSON}. Reason: ${error}`));
// Show data from feature in popUp?
/**
* @type {L.GeoJSON} layer
*/
const layer = new L.geoJson(geo, {
style: function () {
return options;
@@ -545,6 +611,8 @@ GIS.loadSiteLayer = async function (site, options, popup = true, area = false) {
}
});
layer.options.id = site.gisId;
return layer;
}
/**
@@ -595,23 +663,28 @@ GIS.cacheDBData = async function (layerId, dbId) {
* @returns {string} The popup's content
*/
GIS.featurePopup = function (layerName, feature) {
const html = `
<table class="table is-striped is-size-6 m-2">
<tr><th>Oggetto</th><td>${feature.properties.OGGETTO ?? 'n.d.'}</td></tr>
<tr><th>Anno</th><td>${feature.properties.ANNO}</td></tr>
<tr><th>Comune</th><td>${capitalize(feature.properties.COMUNE)}</td></tr>
<tr><th>Località</th><td>${capitalize(feature.properties.LOCALITA) ?? 'n.d.'}</td></tr>
<tr><th>Proprietà</th><td>${capitalize(feature.properties.PROPRIETA) ?? 'n.d.'}</td></tr>
<tr><th>Foglio</th><td>${feature.properties.FOGLIO}</td></tr>
<tr><th>Particella</th><td>${feature.properties.PART_BIS ?? 'n.d.'}</td></tr>
</table>
`;
const content = {
'vincoli.geojson' : html,
'paesistici.geojson' : html,
};
const html = String.raw;
return content[layerName];
let content = html`
<table class="table is-striped is-size-6 m-2">
`;
for (let key of Object.keys(feature.properties)) {
const label = key === 'PART_BIS' ? 'Particella' :
key === 'PROPRIETA' ? 'Proprietà' :
key === 'LOCALITA' ? 'Località' :
key;
if (key !== 'PERCENTUAL' && key !== 'AREA' && key.toLowerCase() !== 'id') {
content += html`
<tr><th>${capitalize(label.toLocaleLowerCase())}</th><td>${capitalize(feature.properties[key]) ?? 'n.d.'}</td></tr>
`;
}
}
content += '</table>'
return content;
}
/**
* Reproject WMS layer to map's CRS