Add cartography menu with image overlays (WIP)
This commit is contained in:
parent
ecd5db5b4c
commit
8ebaea2ff8
@ -158,12 +158,12 @@ a:visited {
|
|||||||
left: 35vw;
|
left: 35vw;
|
||||||
}
|
}
|
||||||
/* Menu overlay */
|
/* Menu overlay */
|
||||||
#menu {
|
.menu-overlay {
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
margin-top: 54px;
|
margin-top: 54px;
|
||||||
}
|
}
|
||||||
#menu.is-overlay {
|
.menu-overlay.is-overlay {
|
||||||
left: auto;
|
left: auto;
|
||||||
}
|
}
|
||||||
/* Content in tabs */
|
/* Content in tabs */
|
||||||
|
@ -25,7 +25,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" data-action="menu-ready@document->menu#buildMenu">
|
<body data-controller="menu"
|
||||||
|
data-action="menu-ready@document->menu#buildMenu menu-ready@document->menu#buildCartographyMenu">
|
||||||
<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">
|
||||||
@ -46,12 +47,21 @@
|
|||||||
<hr class="navbar-divider">
|
<hr class="navbar-divider">
|
||||||
<div class="navbar-end pb-1 pt-1" id="nav-menu">
|
<div class="navbar-end pb-1 pt-1" id="nav-menu">
|
||||||
<button class="navbar-item button is-size-5 is-white mr-3" role="button"
|
<button class="navbar-item button is-size-5 is-white mr-3" role="button"
|
||||||
|
data-id="main"
|
||||||
data-action="menu#toggleMenu">
|
data-action="menu#toggleMenu">
|
||||||
<span class="icon mr-2">
|
<span class="icon mr-2">
|
||||||
<i class="fa fa-list"></i>
|
<i class="fa fa-list"></i>
|
||||||
</span>
|
</span>
|
||||||
Elenco beni
|
Elenco beni
|
||||||
</button>
|
</button>
|
||||||
|
<button class="navbar-item button is-size-5 is-white mr-3" role="button"
|
||||||
|
data-id="cartography"
|
||||||
|
data-action="menu#toggleMenu">
|
||||||
|
<span class="icon mr-2">
|
||||||
|
<i class="fa fa-map"></i>
|
||||||
|
</span>
|
||||||
|
Cartografia
|
||||||
|
</button>
|
||||||
<button class="button is-outlined is-rounded is-link mr-4 mt-1" id="howto" title="Istruzioni">
|
<button class="button is-outlined is-rounded is-link mr-4 mt-1" id="howto" title="Istruzioni">
|
||||||
<span class="icon is-large has-text-link">
|
<span class="icon is-large has-text-link">
|
||||||
<i class="fas fa-question fa-lg"></i>
|
<i class="fas fa-question fa-lg"></i>
|
||||||
@ -69,7 +79,7 @@
|
|||||||
<progress id="map-progress" class="p-2 progress is-medium is-link" aria-label="Map loading..." />
|
<progress id="map-progress" class="p-2 progress is-medium is-link" aria-label="Map loading..." />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-hidden is-4 is-4-desktop is-5-mobile is-pulled-right is-overlay has-background-white-ter" id="menu"
|
<div class="menu-overlay column is-hidden is-4 is-4-desktop is-5-mobile is-pulled-right is-overlay has-background-white-ter"
|
||||||
data-menu-target="menu" data-controller="layer">
|
data-menu-target="menu" data-controller="layer">
|
||||||
<!-- Template to build menu items dynamically -->
|
<!-- Template to build menu items dynamically -->
|
||||||
<template id="menu-item-template">
|
<template id="menu-item-template">
|
||||||
@ -256,6 +266,35 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="menu-overlay column is-hidden is-3 is-3-desktop is-4-mobile is-pulled-right is-overlay has-background-white-ter"
|
||||||
|
data-menu-target="cartography">
|
||||||
|
<!-- Template to build menu items dynamically -->
|
||||||
|
<template id="cartography-item-template">
|
||||||
|
<li>
|
||||||
|
<label class="checkbox">
|
||||||
|
<input type="checkbox"
|
||||||
|
data-controller="layer"
|
||||||
|
data-action="layer#toggleCartography"
|
||||||
|
data-layer-id-value=""
|
||||||
|
data-layer-type-value=""
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
<aside class="menu ml-4 mt-3" data-id="cartography-aside">
|
||||||
|
<button title="Chiudi menu" class="delete is-pulled-right" data-action="menu#close"></button>
|
||||||
|
<p class="menu-label is-size-5 mt-2 is-clickable" data-id="historic">
|
||||||
|
<span role="button" data-action="click->menu#toggle" data-id="historic">
|
||||||
|
Catasto storico
|
||||||
|
<!--
|
||||||
|
<span class="icon pl-2">
|
||||||
|
<i class="fa fa-chevron-right" data-menu-target="icon" data-id="historic"></i>
|
||||||
|
</span>
|
||||||
|
-->
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Bibliography citations template -->
|
<!-- Bibliography citations template -->
|
||||||
<template id="biblio-item-template">
|
<template id="biblio-item-template">
|
||||||
|
@ -1,8 +1,37 @@
|
|||||||
import { Controller } from "@hotwired/stimulus";
|
import { Controller } from "@hotwired/stimulus";
|
||||||
import { GisState } from "../state.js";
|
import { GisState } from "../state.js";
|
||||||
|
import GIS from "../gis.js";
|
||||||
|
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
static targets = ['sites', 'findings', 'notconserved', 'prehist',];
|
static targets = [
|
||||||
|
'sites',
|
||||||
|
'findings',
|
||||||
|
'notconserved',
|
||||||
|
'prehist',
|
||||||
|
];
|
||||||
|
|
||||||
|
static values = {
|
||||||
|
'id': Number,
|
||||||
|
'type': String,
|
||||||
|
};
|
||||||
|
|
||||||
|
async toggleCartography() {
|
||||||
|
const map = GisState.map;
|
||||||
|
const id = this.idValue;
|
||||||
|
|
||||||
|
let currentLayer = await GIS.getImageOverlay(id);
|
||||||
|
let hasLayer = false;
|
||||||
|
|
||||||
|
map.eachLayer(function (layer) {
|
||||||
|
if (layer.options.label === currentLayer.options.label) {
|
||||||
|
hasLayer |= true;
|
||||||
|
currentLayer = layer;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!hasLayer) currentLayer.addTo(map);
|
||||||
|
else map.removeLayer(currentLayer);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @todo Use Stimulus values?
|
* @todo Use Stimulus values?
|
||||||
|
@ -2,7 +2,17 @@ import { Controller } from "@hotwired/stimulus"
|
|||||||
import { GisState } from '../state.js';
|
import { GisState } from '../state.js';
|
||||||
|
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
static targets = ['list', 'menu', 'icon'];
|
static targets = [
|
||||||
|
'list',
|
||||||
|
'menu',
|
||||||
|
'cartography',
|
||||||
|
'icon'
|
||||||
|
];
|
||||||
|
|
||||||
|
static values = {
|
||||||
|
'cartography' : String,
|
||||||
|
'main' : String,
|
||||||
|
};
|
||||||
|
|
||||||
buildMenu() {
|
buildMenu() {
|
||||||
const groups = Object.keys(GisState.markers);
|
const groups = Object.keys(GisState.markers);
|
||||||
@ -17,7 +27,6 @@ export default class extends Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {String} group
|
* @param {String} group
|
||||||
@ -47,8 +56,50 @@ export default class extends Controller {
|
|||||||
return ul;
|
return ul;
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleMenu() {
|
buildCartographyMenu() {
|
||||||
this.menuTarget.classList.toggle('is-hidden');
|
const historicCadastre = GisState.cartography.historic;
|
||||||
|
const template = document.getElementById('cartography-item-template');
|
||||||
|
const ul = document.createElement('ul');
|
||||||
|
ul.className = 'menu-list';
|
||||||
|
ul.id = 'historic-sub';
|
||||||
|
|
||||||
|
const aside = document.querySelector('[data-id="cartography-aside"]');
|
||||||
|
|
||||||
|
for (let geoImage of historicCadastre) {
|
||||||
|
const clone = template.content.cloneNode(true);
|
||||||
|
const label = clone.querySelector('label');
|
||||||
|
const checkbox = clone.querySelector('input[type="checkbox"]');
|
||||||
|
|
||||||
|
checkbox.dataset.layerIdValue = geoImage.id;
|
||||||
|
checkbox.dataset.layerTypeValue = 'historic';
|
||||||
|
const span = document.createElement('span');
|
||||||
|
span.className = 'pl-3';
|
||||||
|
span.textContent = geoImage.label;
|
||||||
|
label.appendChild(span);
|
||||||
|
|
||||||
|
ul.appendChild(clone);
|
||||||
|
}
|
||||||
|
|
||||||
|
aside.appendChild(ul);
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleMenu(event) {
|
||||||
|
const menuId = event.target.dataset.id;
|
||||||
|
|
||||||
|
// Stupid...
|
||||||
|
if (menuId === 'main') {
|
||||||
|
this.menuTarget.classList.toggle('is-hidden');
|
||||||
|
if (!this.cartographyTarget.classList.contains('is-hidden')) {
|
||||||
|
this.cartographyTarget.classList.add('is-hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (menuId === 'cartography') {
|
||||||
|
this.cartographyTarget.classList.toggle('is-hidden');
|
||||||
|
if (!this.menuTarget.classList.contains('is-hidden')) {
|
||||||
|
this.menuTarget.classList.add('is-hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
|
@ -113,13 +113,12 @@ GIS.initMap = async function (mapId, zoomLevel = this.INIT_ZOOM) {
|
|||||||
let layerPaesistici = await this.loadGeoJSON('paesistici.geojson', optionsPaesistici);
|
let layerPaesistici = await this.loadGeoJSON('paesistici.geojson', optionsPaesistici);
|
||||||
|
|
||||||
await this.addLayerGroups(map);
|
await this.addLayerGroups(map);
|
||||||
|
await this.fetchCartographyLayers();
|
||||||
const historicCadastre = await this.imageOverlays();
|
|
||||||
|
|
||||||
const archeo = {
|
const archeo = {
|
||||||
'Vincoli archeologici' : layerVincoli,
|
'Vincoli archeologici' : layerVincoli,
|
||||||
'Vincoli paesistici' : layerPaesistici,
|
'Vincoli paesistici' : layerPaesistici,
|
||||||
'Catasto storico' : historicCadastre,
|
//'Catasto storico' : historicCadastre,
|
||||||
};
|
};
|
||||||
L.control.layers(baseMap, archeo).addTo(map);
|
L.control.layers(baseMap, archeo).addTo(map);
|
||||||
|
|
||||||
@ -128,35 +127,45 @@ GIS.initMap = async function (mapId, zoomLevel = this.INIT_ZOOM) {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Load georeferenced image overlays layer group
|
* Fetches references to cartography layers
|
||||||
|
* and updates GisState
|
||||||
*/
|
*/
|
||||||
GIS.imageOverlays = async function () {
|
GIS.fetchCartographyLayers = async function () {
|
||||||
const data = await this._fetchData('geoimage')
|
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}`));
|
||||||
|
|
||||||
const overlays = L.layerGroup();
|
for (let item of data) {
|
||||||
|
let {id, label} = item;
|
||||||
for (let image of data) {
|
GisState.cartography.historic.push({id, label});
|
||||||
let polygonCoords = JSON.parse(image.polygon).coordinates[0];
|
|
||||||
// Image rectangle bounds are SE and NW coordinates from the PostGIS polygon
|
|
||||||
// with long/lat swapped...
|
|
||||||
const se = [polygonCoords[0][1], polygonCoords[0][0]];
|
|
||||||
const nw = [polygonCoords[2][1], polygonCoords[2][0]];
|
|
||||||
const bounds = [se, nw];
|
|
||||||
|
|
||||||
const imageOverlay = L.imageOverlay(
|
|
||||||
`/webgis/img/geo/${image.filename}`,
|
|
||||||
bounds,
|
|
||||||
{
|
|
||||||
opacity: 0.8,
|
|
||||||
alt: `Immagine georeferita dal catasto storico di Capri`
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
overlays.addLayer(imageOverlay);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Load georeferenced image overlays layer group
|
||||||
|
* @param {Number} imageId - The API id of the georeferenced image
|
||||||
|
* @returns {L.ImageOverlay}
|
||||||
|
*/
|
||||||
|
GIS.getImageOverlay = async function (imageId) {
|
||||||
|
const imageData = await this._fetchData(`geoimages/${imageId}`)
|
||||||
|
.catch(error => console.error(`Could not fetch data for geo image ${imageId}: ${error}`));
|
||||||
|
|
||||||
return overlays;
|
let polygonCoords = JSON.parse(imageData.polygon).coordinates[0];
|
||||||
|
// Image rectangle bounds are SE and NW coordinates from the PostGIS polygon
|
||||||
|
// with long/lat swapped...
|
||||||
|
const se = [polygonCoords[0][1], polygonCoords[0][0]];
|
||||||
|
const nw = [polygonCoords[2][1], polygonCoords[2][0]];
|
||||||
|
const bounds = [se, nw];
|
||||||
|
|
||||||
|
const imageOverlay = L.imageOverlay(
|
||||||
|
`/webgis/img/geo/${imageData.filename}`,
|
||||||
|
bounds,
|
||||||
|
{
|
||||||
|
opacity: 0.8,
|
||||||
|
alt: `Immagine georeferita (${imageData.label})`,
|
||||||
|
label: `geoimage:${imageData.id}:${imageData.label}`,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return imageOverlay;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Add layer groups to map
|
* Add layer groups to map
|
||||||
|
@ -11,10 +11,11 @@
|
|||||||
/**
|
/**
|
||||||
* @typedef {Object} GisStateType
|
* @typedef {Object} GisStateType
|
||||||
* @property {L.Map|null} map
|
* @property {L.Map|null} map
|
||||||
* @property {String|null} apiUrl
|
|
||||||
* @property {MarkerLookup} markers
|
* @property {MarkerLookup} markers
|
||||||
* @property {LayerGroupLookup} layers
|
* @property {LayerGroupLookup} layers
|
||||||
* @property {Object|null} bibliography
|
* @property {Object|null} bibliography
|
||||||
|
* @property {String|null} apiUrl
|
||||||
|
* @property {Object} cartography
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @type {GisStateType} */
|
/** @type {GisStateType} */
|
||||||
@ -36,6 +37,9 @@ export const GisState = {
|
|||||||
},
|
},
|
||||||
bibliography: null,
|
bibliography: null,
|
||||||
apiUrl : null,
|
apiUrl : null,
|
||||||
|
cartography : {
|
||||||
|
historic: [],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,31 +68,6 @@ UI.toggleBurger = function(burgerClass) {
|
|||||||
document.querySelector(`#${menuId}`).classList.toggle('is-active');
|
document.querySelector(`#${menuId}`).classList.toggle('is-active');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Toggle side menu
|
|
||||||
* @param {string} triggerId The ID of the trigger element
|
|
||||||
* @param {?string} listId The ID of the menu list to open (if any)
|
|
||||||
*/
|
|
||||||
UI.toggleMenu = function (triggerId, listId = null) {
|
|
||||||
const trigger = document.querySelector(`#${triggerId}`);
|
|
||||||
const menu = document.querySelector('#menu');
|
|
||||||
trigger.addEventListener('click', () => {
|
|
||||||
menu.classList.remove('is-hidden');
|
|
||||||
//menu.classList.add('is-3');
|
|
||||||
const lists = menu.querySelectorAll('ul');
|
|
||||||
|
|
||||||
if (listId !== null) {
|
|
||||||
const list = document.querySelector(`#${listId}`);
|
|
||||||
list.classList.remove('is-hidden');
|
|
||||||
|
|
||||||
for (let ul of lists) {
|
|
||||||
if (ul.id !== listId && !ul.id.includes('sub')) {
|
|
||||||
ul.classList.add('is-hidden');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Open a modal with DB site data
|
* Open a modal with DB site data
|
||||||
* @param {object} data The data retrieved from the DB to display as modal content
|
* @param {object} data The data retrieved from the DB to display as modal content
|
||||||
|
Loading…
Reference in New Issue
Block a user