Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebc33fe53e | ||
|
|
1c807cdc86 | ||
|
|
91b1764913 | ||
|
|
ace42261cf |
+15
@@ -211,3 +211,18 @@ input:invalid {
|
|||||||
.mixed-tech {
|
.mixed-tech {
|
||||||
color: #f0280f;
|
color: #f0280f;
|
||||||
}
|
}
|
||||||
|
/* Building view top bar */
|
||||||
|
.bview-bar {
|
||||||
|
position: absolute;
|
||||||
|
top: 4rem;
|
||||||
|
width: 450px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
/* Map container border for building view */
|
||||||
|
.bview-active {
|
||||||
|
border:#263aac 4px solid;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #aad3df;
|
||||||
|
}
|
||||||
@@ -17,5 +17,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"standard": "^17.1.2"
|
"standard": "^17.1.2"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "symfony server:start --port=3000"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"name": "reticolata",
|
||||||
|
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
|
||||||
|
"features": [
|
||||||
|
{ "type": "Feature", "properties": { "id": null, "Comune": "Capri", "Località ": "Bagni di Tiberio", "Tipologia": "Struttura Muraria", "Tecnica": "Opera reticolata", "Materiale": "Tufo", "Funzione": null, "Descrizione": "Murature di fondo e divisorie degli ambienti prospicienti il mare, posti all’estremità orientale del complesso dei Bagni di Tiberio", "Elemento": "Alzati", "Componenti": "Cubilia e Blocchetti di ammorsamento angolari" }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ 14.229777980072088, 40.559287936017519 ], [ 14.229767127017078, 40.559288012101483 ], [ 14.22976727121063, 40.559297587195999 ], [ 14.229760323645737, 40.559297626052299 ], [ 14.229760154396285, 40.559286387060112 ], [ 14.229750772025486, 40.559286469247525 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "id": null, "Comune": "Capri", "LocalitĂ ": "Bagni di Tiberio", "Tipologia": "Struttura Muraria", "Tecnica": "Opera Reticolata", "Materiale": "Tufo", "Funzione": null, "Descrizione": "Lacerto murario in giacitura secondaria, riferibile a una struttura con fondazione in opera cementizia e alzato in opera reticolata", "Elemento": "alzato, attacco di fondazione", "Componenti": "Cubilia, scapoli di calcare, scapoli di tufo" }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ 14.229748638716192, 40.559312774822097 ], [ 14.229749854780234, 40.559313917882307 ], [ 14.229749311598642, 40.559316242764893 ], [ 14.229747641045932, 40.559318431170922 ], [ 14.229745404602166, 40.559318825800922 ], [ 14.229707320793663, 40.559318057726777 ], [ 14.229688319593144, 40.559316631832786 ], [ 14.229687414956194, 40.55931462813308 ], [ 14.229689070847257, 40.559311784892955 ], [ 14.229707054884152, 40.559311704425618 ], [ 14.22973485378067, 40.5593122650738 ], [ 14.229745138689067, 40.559312472499833 ], [ 14.229748638716192, 40.559312774822097 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "id": null, "Comune": "Capri", "Località ": "Bagni di Tiberio", "Tipologia": "Strutture murarie", "Tecnica": "Opera reticolata", "Materiale": "Tufo", "Funzione": null, "Descrizione": "Due murature, rispettivamente di fondo e laterale, pertinenti a un ambiente prospiciente il mare nell’area orientale del complesso dei Bagni di Tiberio", "Elemento": "Alzati", "Componenti": "Cubilia, blocchetti di tufo angolari e terminali" }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ 14.229694021609493, 40.55930762924018 ], [ 14.229694082338904, 40.559310341259078 ], [ 14.229682272612358, 40.559310495088383 ], [ 14.229616809841877, 40.559314335557936 ], [ 14.229615693144396, 40.559336306937055 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "id": null, "Comune": "Capri", "Località ": "Bagni di Tiberio", "Tipologia": "Strutture Murarie", "Tecnica": "Opera reticolata", "Materiale": "Tufo", "Funzione": null, "Descrizione": "Due murature pertinenti a un ambiente ubicato sul livello superiore dell’area occidentale del complesso dei Bagni di Tiberio.", "Elemento": "alzati", "Componenti": "cubilia, blocchetti di ammorsamento" }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ 14.229012969950622, 40.559279324646354 ], [ 14.22901299762786, 40.559273288155325 ], [ 14.228949305222281, 40.559271595449403 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "id": null, "Comune": "Capri", "LocalitĂ ": "Bagni di Tiberio", "Tipologia": "Strutture Murarie", "Tecnica": "Opera reticolata", "Materiale": "Tufo", "Funzione": null, "Descrizione": "muratura in pessimo stato di conservazione, inglobata in costruzione moderna", "Elemento": "Alzato", "Componenti": "Cubilia" }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ 14.228945620292212, 40.559244814778907 ], [ 14.228945097860407, 40.559260882019025 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "id": null, "Comune": "Capri", "LocalitĂ ": "Bagni di Tiberio", "Tipologia": "Struttura Muraria", "Tecnica": "Opera reticolata", "Materiale": "Tufo", "Funzione": "sostruttiva", "Descrizione": "Fondazione del terrazzamento prospiciente il mare, con porticato soprastante", "Elemento": "Fondazione", "Componenti": "Cubilia" }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ 14.22932061572207, 40.559368986602642 ], [ 14.229319898205036, 40.559370575004976 ], [ 14.229315830697367, 40.559373603453658 ], [ 14.229313913113851, 40.559377741595505 ] ] ] } }
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bricks" viewBox="0 0 16 16">
|
||||||
|
<path d="M0 .5A.5.5 0 0 1 .5 0h15a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-.5.5H14v2h1.5a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-.5.5H14v2h1.5a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-.5.5H.5a.5.5 0 0 1-.5-.5v-3a.5.5 0 0 1 .5-.5H2v-2H.5a.5.5 0 0 1-.5-.5v-3A.5.5 0 0 1 .5 6H2V4H.5a.5.5 0 0 1-.5-.5zM3 4v2h4.5V4zm5.5 0v2H13V4zM3 10v2h4.5v-2zm5.5 0v2H13v-2zM1 1v2h3.5V1zm4.5 0v2h5V1zm6 0v2H15V1zM1 7v2h3.5V7zm4.5 0v2h5V7zm6 0v2H15V7zM1 13v2h3.5v-2zm4.5 0v2h5v-2zm6 0v2H15v-2z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 574 B |
+2
-2
@@ -26,8 +26,8 @@
|
|||||||
<script src="js/index.js" type="module"></script>
|
<script src="js/index.js" type="module"></script>
|
||||||
<title>WebGIS Isola di Capri</title>
|
<title>WebGIS Isola di Capri</title>
|
||||||
</head>
|
</head>
|
||||||
<body data-controller="menu modal"
|
<body data-controller="menu modal bview"
|
||||||
data-action="menu-ready@document->menu#buildMenu menu-ready@document->menu#buildCartographyMenu">
|
data-action="menu-ready@document->menu#buildMenu menu-ready@document->menu#buildCartographyMenu keydown.esc->bview#closeView">
|
||||||
<nav class="navbar mb-0" role="navigation">
|
<nav class="navbar mb-0" role="navigation">
|
||||||
<div class="navbar-brand">
|
<div class="navbar-brand">
|
||||||
<a href="/" class="navbar-item is-size-5 has-text-dark ml-4" title="Torna alla home page">
|
<a href="/" class="navbar-item is-size-5 has-text-dark ml-4" title="Torna alla home page">
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { Controller } from "@hotwired/stimulus"
|
||||||
|
import { GisState } from '../state.js';
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
static targets = ['bar'];
|
||||||
|
|
||||||
|
closeView(event) {
|
||||||
|
// Don't do anything if ESC keyboard event
|
||||||
|
// is not fired from the building view
|
||||||
|
if (event instanceof KeyboardEvent && !GisState.bViewActive) return;
|
||||||
|
|
||||||
|
this.resetMap();
|
||||||
|
this.barTarget.remove();
|
||||||
|
GisState.bViewActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetMap() {
|
||||||
|
// Restore previous map state before closing view
|
||||||
|
const map = GisState.map;
|
||||||
|
map.removeLayer(GisState.baseLayers['Limiti amministrativi']);
|
||||||
|
//map.removeLayer(GisState.cartography.buildings);
|
||||||
|
|
||||||
|
const walls = GisState.layers.walls;
|
||||||
|
|
||||||
|
// map.removeLayer(GisState.layers.walls) doesn't work, i.e.
|
||||||
|
// it doesn't remove the layer group (fails silently)
|
||||||
|
walls.eachLayer(layer => map.removeLayer(layer));
|
||||||
|
|
||||||
|
GisState.layers.walls.removeFrom(map);
|
||||||
|
map.addLayer(GisState.currentMapState.baseLayer);
|
||||||
|
map.setMinZoom(GisState.currentMapState.minZoom);
|
||||||
|
map.setMaxZoom(GisState.currentMapState.maxZoom);
|
||||||
|
map.setView(
|
||||||
|
GisState.currentMapState.center,
|
||||||
|
GisState.currentMapState.zoom
|
||||||
|
);
|
||||||
|
map._container.classList.remove('bview-border');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,8 @@ export default class extends Controller {
|
|||||||
'menu',
|
'menu',
|
||||||
'cartography',
|
'cartography',
|
||||||
'search',
|
'search',
|
||||||
'icon'
|
'icon',
|
||||||
|
'element',
|
||||||
];
|
];
|
||||||
|
|
||||||
static values = {
|
static values = {
|
||||||
@@ -169,4 +170,8 @@ export default class extends Controller {
|
|||||||
|
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeElement() {
|
||||||
|
this.elementTarget.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+101
-30
@@ -6,9 +6,19 @@ import Icons from "./icons.js";
|
|||||||
import { SphericalPhoto } from "./components/SphericalPhoto.js";
|
import { SphericalPhoto } from "./components/SphericalPhoto.js";
|
||||||
import { GisState } from "./state.js";
|
import { GisState } from "./state.js";
|
||||||
import Options from "./layer_options.js";
|
import Options from "./layer_options.js";
|
||||||
|
import { saveCurrentState } from "./map.js";
|
||||||
|
|
||||||
const MAPBOX_TOKEN = 'pk.eyJ1Ijoibmljb3BhIiwiYSI6ImNseWNwZjJjbjFidzcya3BoYTU0bHg4NnkifQ.3036JnCXZTEMt6jVgMzVRw';
|
const MAPBOX_TOKEN = 'pk.eyJ1Ijoibmljb3BhIiwiYSI6ImNseWNwZjJjbjFidzcya3BoYTU0bHg4NnkifQ.3036JnCXZTEMt6jVgMzVRw';
|
||||||
const BASE_URL = location.href;
|
const BASE_URL = location.href;
|
||||||
|
// TODO: Use DB to handle these?
|
||||||
|
const WALL_TECHNIQUES = [
|
||||||
|
'reticolata',
|
||||||
|
'incerta',
|
||||||
|
'mista',
|
||||||
|
'laterizia',
|
||||||
|
'cementizia',
|
||||||
|
'poligonale',
|
||||||
|
];
|
||||||
|
|
||||||
let API_URL = API_CONFIG.prod;
|
let API_URL = API_CONFIG.prod;
|
||||||
|
|
||||||
@@ -40,15 +50,8 @@ export const INIT_ZOOM = 14;
|
|||||||
*/
|
*/
|
||||||
function capitalize(text) {
|
function capitalize(text) {
|
||||||
let capital = text;
|
let capital = text;
|
||||||
if (text) {
|
if (text !== null && text !== undefined && text.at && text.length) {
|
||||||
let words = text.split(' ');
|
capital = text.at(0).toLocaleUpperCase() + text.slice(1);
|
||||||
capital = '';
|
|
||||||
|
|
||||||
for (let w of words) {
|
|
||||||
w = w[0].toUpperCase() + w.slice(1);
|
|
||||||
capital += w + ' ';
|
|
||||||
}
|
|
||||||
capital.trimEnd();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return capital;
|
return capital;
|
||||||
@@ -62,6 +65,7 @@ GIS.initMap = async function (mapId, zoomLevel = this.INIT_ZOOM) {
|
|||||||
let map = L.map(mapId, {
|
let map = L.map(mapId, {
|
||||||
//attributionControl: false,
|
//attributionControl: false,
|
||||||
minZoom: GIS.MIN_ZOOM,
|
minZoom: GIS.MIN_ZOOM,
|
||||||
|
maxZoom: GIS.MAX_ZOOM,
|
||||||
}).setView(this.CENTER_COORDS, zoomLevel);
|
}).setView(this.CENTER_COORDS, zoomLevel);
|
||||||
|
|
||||||
map.crs = L.CRS.EPSG4326;
|
map.crs = L.CRS.EPSG4326;
|
||||||
@@ -102,15 +106,68 @@ GIS.initMap = async function (mapId, zoomLevel = this.INIT_ZOOM) {
|
|||||||
};
|
};
|
||||||
L.control.layers(baseMap, cartography).addTo(map);
|
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.map = map;
|
||||||
|
GisState.cartography.buildings = buildings;
|
||||||
|
|
||||||
return map;
|
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;
|
||||||
|
saveCurrentState(map);
|
||||||
|
let currentBase = GisState.currentMapState.baseLayer;
|
||||||
|
|
||||||
|
map.removeLayer(currentBase);
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// Cache!
|
||||||
|
const wallLayer = await this.loadGeoJSON(
|
||||||
|
`murarie/${layerId}/reticolata.geojson`,
|
||||||
|
// TODO: create color lookup table...
|
||||||
|
Options.walls,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
wallLayer.addTo(map);
|
||||||
|
|
||||||
|
// The group of all added walls...
|
||||||
|
GisState.layers.walls = L.layerGroup([wallLayer]);
|
||||||
|
|
||||||
|
map.setView(
|
||||||
|
wallLayer.getBounds().getCenter(),
|
||||||
|
20,
|
||||||
|
{animate: false},
|
||||||
|
);
|
||||||
|
map.setMinZoom(19);
|
||||||
|
map.setMaxZoom(25);
|
||||||
|
// This is terrible...
|
||||||
|
UI.addBuildingViewBar();
|
||||||
|
map._container.classList.add('bview-active');
|
||||||
|
GisState.bViewActive = true;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Fetches references to cartography layers
|
* Fetches references to cartography layers
|
||||||
* and updates GisState
|
* and updates GisState
|
||||||
*/
|
*/
|
||||||
GIS.fetchCartographyLayers = async function () {
|
GIS.fetchCartographyLayers = async function() {
|
||||||
const data = await this._fetchData('geoimages/menu')
|
const data = await this._fetchData('geoimages/menu')
|
||||||
.catch(error => console.error(`Could not fetch data for geo images: ${error}`));
|
.catch(error => console.error(`Could not fetch data for geo images: ${error}`));
|
||||||
|
|
||||||
@@ -187,6 +244,9 @@ GIS.addLayerGroups = async function (map) {
|
|||||||
sites.markers.addTo(map);
|
sites.markers.addTo(map);
|
||||||
sites.geom.addTo(map);
|
sites.geom.addTo(map);
|
||||||
|
|
||||||
|
// A layer group with all site geometries (GeoJSON)
|
||||||
|
GisState.layers.geometries = sites.geom;
|
||||||
|
|
||||||
const groups = await Promise.all(
|
const groups = await Promise.all(
|
||||||
[
|
[
|
||||||
this.notConserved(),
|
this.notConserved(),
|
||||||
@@ -213,7 +273,7 @@ GIS.sites = async function () {
|
|||||||
if (record.geojson) {
|
if (record.geojson) {
|
||||||
const options = record.gisId === 'grotta_azzurra' ?
|
const options = record.gisId === 'grotta_azzurra' ?
|
||||||
Options.grotta : Options.site;
|
Options.grotta : Options.site;
|
||||||
geom.push(await this.loadSiteLayer(record, options));
|
geom.push(await this.loadSiteLayer(record, options, false));
|
||||||
}
|
}
|
||||||
if (record.area) {
|
if (record.area) {
|
||||||
const options = record.gisId === 'villa_bismarck' ?
|
const options = record.gisId === 'villa_bismarck' ?
|
||||||
@@ -412,7 +472,6 @@ GIS.reuse = async function () {
|
|||||||
* @returns {{baseMap: {"OpenStreetMap": L.TileLayer}}}
|
* @returns {{baseMap: {"OpenStreetMap": L.TileLayer}}}
|
||||||
*/
|
*/
|
||||||
GIS.initLayers = async function(map) {
|
GIS.initLayers = async function(map) {
|
||||||
|
|
||||||
let osmap = new L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
let osmap = new L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
maxNativeZoom : GIS.MAX_ZOOM,
|
maxNativeZoom : GIS.MAX_ZOOM,
|
||||||
maxZoom: GIS.MAX_ZOOM,
|
maxZoom: GIS.MAX_ZOOM,
|
||||||
@@ -437,6 +496,8 @@ GIS.initLayers = async function(map) {
|
|||||||
'Limiti amministrativi' : boundaries,
|
'Limiti amministrativi' : boundaries,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GisState.baseLayers = baseMap;
|
||||||
|
|
||||||
return baseMap;
|
return baseMap;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -466,7 +527,7 @@ GIS.toggleSpherical = async function(map) {
|
|||||||
});
|
});
|
||||||
modal.querySelector('.modal-close').addEventListener('click', () => {
|
modal.querySelector('.modal-close').addEventListener('click', () => {
|
||||||
modal.classList.remove('is-active');
|
modal.classList.remove('is-active');
|
||||||
})
|
});
|
||||||
sPhoto.setViewer(pano.filename);
|
sPhoto.setViewer(pano.filename);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -488,7 +549,7 @@ GIS.toggleSpherical = async function(map) {
|
|||||||
* @param {string} geoJSON geoJSON filename
|
* @param {string} geoJSON geoJSON filename
|
||||||
* @param {{color, opacity, weight, fillColor, fillOpacity}} options Style options for features
|
* @param {{color, opacity, weight, fillColor, fillOpacity}} options Style options for features
|
||||||
* @param {boolean} popup Should the features have a popup?
|
* @param {boolean} popup Should the features have a popup?
|
||||||
* @returns {L.Layer}
|
* @returns {L.GeoJSON}
|
||||||
*/
|
*/
|
||||||
GIS.loadGeoJSON = async function (geoJSON, options, popup = true) {
|
GIS.loadGeoJSON = async function (geoJSON, options, popup = true) {
|
||||||
const geo = await fetch(`${BASE_URL}/geojson/${geoJSON}`)
|
const geo = await fetch(`${BASE_URL}/geojson/${geoJSON}`)
|
||||||
@@ -496,6 +557,9 @@ GIS.loadGeoJSON = async function (geoJSON, options, popup = true) {
|
|||||||
.catch(error => console.error(`Can't load layer ${geoJSON}. Reason: ${error}`));
|
.catch(error => console.error(`Can't load layer ${geoJSON}. Reason: ${error}`));
|
||||||
|
|
||||||
// Show data from feature in popUp?
|
// Show data from feature in popUp?
|
||||||
|
/**
|
||||||
|
* @type {L.GeoJSON} layer
|
||||||
|
*/
|
||||||
const layer = new L.geoJson(geo, {
|
const layer = new L.geoJson(geo, {
|
||||||
style: function () {
|
style: function () {
|
||||||
return options;
|
return options;
|
||||||
@@ -545,6 +609,8 @@ GIS.loadSiteLayer = async function (site, options, popup = true, area = false) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
layer.options.id = site.gisId;
|
||||||
|
|
||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -595,23 +661,28 @@ GIS.cacheDBData = async function (layerId, dbId) {
|
|||||||
* @returns {string} The popup's content
|
* @returns {string} The popup's content
|
||||||
*/
|
*/
|
||||||
GIS.featurePopup = function (layerName, feature) {
|
GIS.featurePopup = function (layerName, feature) {
|
||||||
const html = `
|
const html = String.raw;
|
||||||
<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,
|
|
||||||
};
|
|
||||||
|
|
||||||
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
|
* Reproject WMS layer to map's CRS
|
||||||
|
|||||||
+43
-48
@@ -14,61 +14,56 @@ const buildingTechColors = {
|
|||||||
*/
|
*/
|
||||||
const Icons = {};
|
const Icons = {};
|
||||||
|
|
||||||
Icons.site = L.icon(
|
Icons.site = L.icon({
|
||||||
{
|
iconUrl: 'img/icons/siti.png',
|
||||||
iconUrl: 'img/icons/siti.png',
|
iconSize: [18, 27],
|
||||||
iconSize: [18, 27],
|
iconAnchor: [10, 24],
|
||||||
iconAnchor: [10, 24],
|
tooltipAnchor: [0, -22],
|
||||||
tooltipAnchor: [0, -22],
|
});
|
||||||
}
|
Icons.notConserved = L.icon({
|
||||||
);
|
iconUrl: 'img/icons/non_conserv.png',
|
||||||
Icons.notConserved = L.icon(
|
iconSize: [18, 27],
|
||||||
{
|
iconAnchor: [10, 24],
|
||||||
iconUrl: 'img/icons/non_conserv.png',
|
tooltipAnchor: [0, -22],
|
||||||
iconSize: [18, 27],
|
});
|
||||||
iconAnchor: [10, 24],
|
|
||||||
tooltipAnchor: [0, -22],
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Icons.finding = L.icon(
|
Icons.finding = L.icon({
|
||||||
{
|
iconUrl: 'img/icons/rinvenimenti.png',
|
||||||
iconUrl: 'img/icons/rinvenimenti.png',
|
iconSize: [18, 27],
|
||||||
iconSize: [18, 27],
|
iconAnchor: [10, 24],
|
||||||
iconAnchor: [10, 24],
|
tooltipAnchor: [0, -22],
|
||||||
tooltipAnchor: [0, -22],
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Icons.prehistoric = L.icon(
|
Icons.prehistoric = L.icon({
|
||||||
{
|
iconUrl: 'img/icons/preistorici.png',
|
||||||
iconUrl: 'img/icons/preistorici.png',
|
iconSize: [18, 27],
|
||||||
iconSize: [18, 27],
|
iconAnchor: [10, 24],
|
||||||
iconAnchor: [10, 24],
|
tooltipAnchor: [0, -22],
|
||||||
tooltipAnchor: [0, -22],
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Icons.underwater = L.icon(
|
Icons.underwater = L.icon({
|
||||||
{
|
iconUrl: 'img/icons/subacquei.png',
|
||||||
iconUrl: 'img/icons/subacquei.png',
|
iconSize: [18, 27],
|
||||||
iconSize: [18, 27],
|
iconAnchor: [10, 24],
|
||||||
iconAnchor: [10, 24],
|
tooltipAnchor: [0, -22],
|
||||||
tooltipAnchor: [0, -22],
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Icons.reuse = L.icon(
|
Icons.reuse = L.icon({
|
||||||
{
|
iconUrl: 'img/icons/reimpiego.png',
|
||||||
iconUrl: 'img/icons/reimpiego.png',
|
iconSize: [18, 27],
|
||||||
iconSize: [18, 27],
|
iconAnchor: [10, 24],
|
||||||
iconAnchor: [10, 24],
|
tooltipAnchor: [0, -22],
|
||||||
tooltipAnchor: [0, -22],
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
Icons.camera = L.divIcon({className: 'fa fa-camera'});
|
Icons.camera = L.divIcon({className: 'fa fa-camera'});
|
||||||
|
|
||||||
|
Icons.wall = L.icon({
|
||||||
|
iconUrl: 'img/icons/bricks.svg',
|
||||||
|
iconSize: [18, 27],
|
||||||
|
iconAnchor: [10, 24],
|
||||||
|
tooltipAnchor: [0, -22],
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns a different color to the icon
|
* Assigns a different color to the icon
|
||||||
* based on building tech type
|
* based on building tech type
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import BiblioController from './controllers/biblio_controller.js';
|
|||||||
import TabsController from './controllers/tabs_controller.js';
|
import TabsController from './controllers/tabs_controller.js';
|
||||||
import LayerController from './controllers/layer_controller.js';
|
import LayerController from './controllers/layer_controller.js';
|
||||||
import SearchController from './controllers/search_controller.js';
|
import SearchController from './controllers/search_controller.js';
|
||||||
|
import BViewController from './controllers/bview_controller.js';
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', async () => {
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
// Register Stimulus controllers
|
// Register Stimulus controllers
|
||||||
@@ -39,4 +40,5 @@ function initStimulus() {
|
|||||||
Stimulus.register("tabs", TabsController);
|
Stimulus.register("tabs", TabsController);
|
||||||
Stimulus.register("layer", LayerController);
|
Stimulus.register("layer", LayerController);
|
||||||
Stimulus.register("search", SearchController);
|
Stimulus.register("search", SearchController);
|
||||||
|
Stimulus.register("bview", BViewController);
|
||||||
}
|
}
|
||||||
@@ -42,15 +42,22 @@ Options.buildings = {
|
|||||||
color: '#222',
|
color: '#222',
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
weight: 1.5,
|
weight: 1.5,
|
||||||
fillColor: '#5a5b5c',
|
fillColor: '#717274',
|
||||||
fillOpacity: 0.8
|
fillOpacity: 0.8
|
||||||
};
|
};
|
||||||
Options.boundaries = {
|
Options.boundaries = {
|
||||||
color: '#222',
|
color: '#222',
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
weight: 1.5,
|
weight: 2,
|
||||||
fillColor: '#b9bdc0',
|
fillColor: '#ebdfccff',
|
||||||
fillOpacity: 0.8
|
fillOpacity: 1,
|
||||||
|
};
|
||||||
|
Options.walls = {
|
||||||
|
color: '#10ee47',
|
||||||
|
fillColor: '#10ee47',
|
||||||
|
fillOpacity: 1,
|
||||||
|
opacity: 1,
|
||||||
|
weight: 4.5,
|
||||||
};
|
};
|
||||||
Options.cluster = {
|
Options.cluster = {
|
||||||
spiderfyOnMaxZoom: false,
|
spiderfyOnMaxZoom: false,
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { GisState } from "./state.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functions / utilities to manipulate the Leaflet map
|
||||||
|
* @module Map
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the current state of the map
|
||||||
|
* @param {L.Map} map
|
||||||
|
*/
|
||||||
|
export function saveCurrentState(map) {
|
||||||
|
let currentBase = {};
|
||||||
|
for (let key of Object.keys(GisState.baseLayers)) {
|
||||||
|
if (map.hasLayer(GisState.baseLayers[key])) {
|
||||||
|
currentBase = GisState.baseLayers[key];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GisState.currentMapState = {
|
||||||
|
baseLayer: currentBase,
|
||||||
|
zoom: map.getZoom(),
|
||||||
|
center: map.getCenter(),
|
||||||
|
minZoom: map.getMinZoom(),
|
||||||
|
maxZoom: map.getMaxZoom(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentState() {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
@@ -8,9 +8,22 @@
|
|||||||
* A lookup table of Leaflet layer groups by category
|
* A lookup table of Leaflet layer groups by category
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} MapState
|
||||||
|
* @property {L.Layer} baseLayer
|
||||||
|
* @property {number} zoom
|
||||||
|
* @property {L.LatLngExpression} center
|
||||||
|
* @property {number} minZoom
|
||||||
|
* @property {number} maxZoom
|
||||||
|
* A representation of the (current) Leaflet map state
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} GisStateType
|
* @typedef {Object} GisStateType
|
||||||
* @property {L.Map|null} map
|
* @property {L.Map|null} map
|
||||||
|
* @property {{string: L.Layer}|null} baseLayers
|
||||||
|
* @property {?MapState} currentMapState
|
||||||
|
* @property {boolean} bViewActive
|
||||||
* @property {MarkerLookup} markers
|
* @property {MarkerLookup} markers
|
||||||
* @property {LayerGroupLookup} layers
|
* @property {LayerGroupLookup} layers
|
||||||
* @property {Object|null} bibliography
|
* @property {Object|null} bibliography
|
||||||
@@ -21,6 +34,9 @@
|
|||||||
/** @type {GisStateType} */
|
/** @type {GisStateType} */
|
||||||
export const GisState = {
|
export const GisState = {
|
||||||
map: null,
|
map: null,
|
||||||
|
baseLayers: null,
|
||||||
|
currentMapState: null,
|
||||||
|
bViewActive: false,
|
||||||
markers: {
|
markers: {
|
||||||
sites: {},
|
sites: {},
|
||||||
notConserved: {},
|
notConserved: {},
|
||||||
@@ -31,6 +47,11 @@ export const GisState = {
|
|||||||
buildingTechs: {},
|
buildingTechs: {},
|
||||||
},
|
},
|
||||||
layers: {
|
layers: {
|
||||||
|
geometries: {},
|
||||||
|
/**
|
||||||
|
* @type {L.LayerGroup}
|
||||||
|
*/
|
||||||
|
walls: {},
|
||||||
sites: {},
|
sites: {},
|
||||||
notConserved: {},
|
notConserved: {},
|
||||||
findings: {},
|
findings: {},
|
||||||
@@ -44,6 +65,7 @@ export const GisState = {
|
|||||||
cartography : {
|
cartography : {
|
||||||
historic: [],
|
historic: [],
|
||||||
cadastral: null,
|
cadastral: null,
|
||||||
|
buildings: null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-1
@@ -42,7 +42,7 @@ UI.addCenterMapControl = function (map, centerCoords, zoom) {
|
|||||||
let controlUI = L.DomUtil.create('a', 'leaflet-draw-edit-remove', controlDiv);
|
let controlUI = L.DomUtil.create('a', 'leaflet-draw-edit-remove', controlDiv);
|
||||||
controlUI.title = 'Centra la mappa';
|
controlUI.title = 'Centra la mappa';
|
||||||
controlUI.href = '#';
|
controlUI.href = '#';
|
||||||
controlUI.innerHTML = `
|
controlUI.innerHTML = html`
|
||||||
<span class="icon is-medium">
|
<span class="icon is-medium">
|
||||||
<i>
|
<i>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="pt-2" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="pt-2" viewBox="0 0 16 16">
|
||||||
@@ -59,6 +59,20 @@ UI.addCenterMapControl = function (map, centerCoords, zoom) {
|
|||||||
let centerCtr = new L.Control.CenterControl();
|
let centerCtr = new L.Control.CenterControl();
|
||||||
map.addControl(centerCtr);
|
map.addControl(centerCtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UI.addBuildingViewBar = function() {
|
||||||
|
const bar = document.createElement('div');
|
||||||
|
bar.className = 'container bview-bar has-background-primary-90 p-3';
|
||||||
|
bar.setAttribute('data-bview-target', 'bar');
|
||||||
|
|
||||||
|
bar.innerHTML = html`
|
||||||
|
<button title="Esci da mappa USM" class="delete is-pulled-right" data-action="bview#closeView"></button>
|
||||||
|
<p class="has-text-centered has-text-weight-semibold is-size-5 p-2">Mappa UnitĂ Stratigrafica Muraria (USM)</p>
|
||||||
|
<p class="has-text-centered is-size-6 mt-0 pt-0">(Chiudere questo riquadro o premere ESC per uscire)</p>
|
||||||
|
`;
|
||||||
|
|
||||||
|
document.body.appendChild(bar);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Toggle burger menu for small screens
|
* Toggle burger menu for small screens
|
||||||
* @param {string} burgerClass The CSS class of the burger element
|
* @param {string} burgerClass The CSS class of the burger element
|
||||||
|
|||||||
Reference in New Issue
Block a user