Crude spherical photos
This commit is contained in:
parent
2650df69a3
commit
760fb3e960
2
.gitignore
vendored
2
.gitignore
vendored
@ -11,3 +11,5 @@ progetto_QGIS/
|
||||
conf.json
|
||||
shapefile
|
||||
config.js
|
||||
# Don't track shperical photos
|
||||
webgis/img/spherical/*.png
|
||||
|
@ -155,4 +155,9 @@ a:visited {
|
||||
.docs-title {
|
||||
width: 300px;
|
||||
max-width: 300px;
|
||||
}
|
||||
/* Panoramas */
|
||||
#pano-viewer {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
0
webgis/img/spherical/.keep
Normal file
0
webgis/img/spherical/.keep
Normal file
@ -6,6 +6,15 @@
|
||||
<link rel="stylesheet" href="../css/app.css" />
|
||||
<link rel="stylesheet" href="js/vendor/spotlight.js/dist/css/spotlight.min.css" />
|
||||
<link rel="stylesheet" href="js/vendor/@kalisio/leaflet-graphicscale/dist/Leaflet.GraphicScale.min.css" />
|
||||
<link rel="stylesheet" href="js/vendor/@photo-sphere-viewer/core/index.css" />
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"three": "./js/vendor/three/build/three.module.js",
|
||||
"@photo-sphere-viewer/core": "./js/vendor/@photo-sphere-viewer/core/index.module.js"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script src="js/vendor/leaflet/dist/leaflet.js"></script>
|
||||
<script src="js/vendor/@kalisio/leaflet-graphicscale/dist/Leaflet.GraphicScale.min.js"></script>
|
||||
<script src="js/index.js" type="module"></script>
|
||||
@ -156,5 +165,13 @@
|
||||
</div>
|
||||
<button class="modal-close is-large" aria-label="close"></button>
|
||||
</div>
|
||||
<!-- Spherical photo modal -->
|
||||
<div class="modal" id="spherical-modal">
|
||||
<div class="modal-background"></div>
|
||||
<div class="modal-content has-background-white" style="min-height: 95vh;">
|
||||
<div id="pano-viewer"></div>
|
||||
</div>
|
||||
<button class="modal-close is-large" aria-label="close"></button>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -65,7 +65,7 @@ export class NotConservedSheet {
|
||||
`;
|
||||
|
||||
this.biblioElements.push(`
|
||||
<div class="p-2" id="ref-${record.id}">
|
||||
<div class="p-2 mt-2" id="ref-${record.id}">
|
||||
<p>${record.reference}</p>
|
||||
</div>
|
||||
`
|
||||
|
18
webgis/js/components/SphericalPhoto.js
Normal file
18
webgis/js/components/SphericalPhoto.js
Normal file
@ -0,0 +1,18 @@
|
||||
import { Viewer } from '@photo-sphere-viewer/core';
|
||||
/**
|
||||
* @class SphericalPhoto
|
||||
*/
|
||||
export class SphericalPhoto {
|
||||
basePath = '/webgis/img/spherical';
|
||||
|
||||
/**
|
||||
* @param {string} filename Name of the spherical image
|
||||
*/
|
||||
setViewer(filename) {
|
||||
new Viewer({
|
||||
container: document.querySelector('#pano-viewer'),
|
||||
panorama: `${this.basePath}/${filename}`,
|
||||
defaultZoomLvl: 0,
|
||||
});
|
||||
}
|
||||
}
|
191
webgis/js/gis.js
191
webgis/js/gis.js
@ -2,6 +2,8 @@
|
||||
|
||||
import UI from "./ui.js";
|
||||
import API_CONFIG from "./config.js";
|
||||
import Icons from "./icons.js";
|
||||
import { SphericalPhoto } from "./components/SphericalPhoto.js";
|
||||
|
||||
const MAPBOX_TOKEN = 'pk.eyJ1Ijoibmljb3BhIiwiYSI6ImNseWNwZjJjbjFidzcya3BoYTU0bHg4NnkifQ.3036JnCXZTEMt6jVgMzVRw';
|
||||
const BASE_URL = location.href;
|
||||
@ -111,85 +113,22 @@ GIS.initMap = async function (mapId, zoomLevel = this.INIT_ZOOM) {
|
||||
});
|
||||
|
||||
let map = L.map(mapId, {
|
||||
attributionControl: false,
|
||||
//attributionControl: false,
|
||||
minZoom: 2,
|
||||
}).setView(this.CENTER_COORDS, zoomLevel);
|
||||
|
||||
map.crs = L.CRS.EPSG4326;
|
||||
|
||||
const {baseMap, sitesGroup} = await this.initLayers(map);
|
||||
|
||||
let layerVincoli = await this.loadLayer('vincoli.geojson', optionsVincoli);
|
||||
let layerPaesistici = await this.loadLayer('paesistici.geojson', optionsPaesistici);
|
||||
let notConserData = await fetch(`${API_URL}/not_conserved`)
|
||||
.then(data => data.json());
|
||||
|
||||
// Add scale and ruler controls
|
||||
L.control.scale({imperial: false}).addTo(map);
|
||||
L.control.graphicScale({fill: 'hollow', position: 'bottomright'}).addTo(map);
|
||||
|
||||
let sitesMarkers = [];
|
||||
let siteIcon = L.icon(
|
||||
{
|
||||
iconUrl: 'img/icons/siti.png',
|
||||
iconSize: [24, 36],
|
||||
iconAnchor: [12, 32],
|
||||
tooltipAnchor: [0, -26],
|
||||
}
|
||||
);
|
||||
let notConserIcon = L.icon(
|
||||
{
|
||||
iconUrl: 'img/icons/non_conserv.png',
|
||||
iconSize: [24, 36],
|
||||
iconAnchor: [12, 32],
|
||||
tooltipAnchor: [0, -26],
|
||||
}
|
||||
);
|
||||
let layerVincoli = await this.loadLayer('vincoli.geojson', optionsVincoli);
|
||||
let layerPaesistici = await this.loadLayer('paesistici.geojson', optionsPaesistici);
|
||||
|
||||
let notConserved = [];
|
||||
|
||||
for (let record of notConserData.records) {
|
||||
notConserved.push(L.marker(
|
||||
record.coordinates,
|
||||
{icon: notConserIcon}
|
||||
).bindTooltip(record.denomination)
|
||||
.on(
|
||||
'click',
|
||||
() => UI.openNotConserModal(record, '#not-conser-data')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
for (let id in MARKER_NAMES.sites) {
|
||||
let layer = sitesGroup.customGetLayer(id);
|
||||
let coords = layer.getBounds().getCenter();
|
||||
const fromStorage = localStorage.getItem(id);
|
||||
let data = {};
|
||||
|
||||
if (fromStorage !== 'undefined') {
|
||||
try {
|
||||
data = JSON.parse(fromStorage);
|
||||
const lat = data?.coordinates[0] ?? coords.lat;
|
||||
const lon = data?.coordinates[1] ?? coords.lng;
|
||||
coords = [lat, lon];
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
} else {
|
||||
data = await GIS._fetchData('site/' + id);
|
||||
}
|
||||
|
||||
const marker = L.marker(coords, { icon: siteIcon })
|
||||
.bindTooltip(MARKER_NAMES.sites[id])
|
||||
.openTooltip();
|
||||
|
||||
marker.on('click', () => UI.openSiteModal(data, '#site-data'));
|
||||
|
||||
sitesMarkers.push(marker);
|
||||
}
|
||||
|
||||
let markersGroup = L.layerGroup(sitesMarkers);
|
||||
let notConservedGroup = L.layerGroup(notConserved);
|
||||
let markersGroup = await this.sitesMarkers(sitesGroup);
|
||||
let notConservedGroup = await this.notConserved();
|
||||
|
||||
const archeo = {
|
||||
'Beni archeologici (punti)' : markersGroup,
|
||||
@ -211,6 +150,68 @@ GIS.initMap = async function (mapId, zoomLevel = this.INIT_ZOOM) {
|
||||
// TODO Horrible?
|
||||
return {map: map, sites: sitesGroup};
|
||||
}
|
||||
/**
|
||||
* Create markers for sites
|
||||
* @param {L.LayerGroup} sitesGroup
|
||||
* @returns {L.LayerGroup}
|
||||
*/
|
||||
GIS.sitesMarkers = async function (sitesGroup) {
|
||||
let sitesMarkers = [];
|
||||
|
||||
for (let id in MARKER_NAMES.sites) {
|
||||
let layer = sitesGroup.customGetLayer(id);
|
||||
let coords = layer.getBounds().getCenter();
|
||||
const fromStorage = localStorage.getItem(id);
|
||||
let data = {};
|
||||
|
||||
if (fromStorage !== 'undefined') {
|
||||
try {
|
||||
data = JSON.parse(fromStorage);
|
||||
const lat = data?.coordinates[0] ?? coords.lat;
|
||||
const lon = data?.coordinates[1] ?? coords.lng;
|
||||
coords = [lat, lon];
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
} else {
|
||||
data = await GIS._fetchData('site/' + id);
|
||||
}
|
||||
|
||||
const marker = L.marker(coords, { icon: Icons.site })
|
||||
.bindTooltip(MARKER_NAMES.sites[id])
|
||||
.openTooltip();
|
||||
|
||||
marker.on('click', () => UI.openSiteModal(data, '#site-data'));
|
||||
|
||||
sitesMarkers.push(marker);
|
||||
}
|
||||
|
||||
return L.layerGroup(sitesMarkers);
|
||||
}
|
||||
/**
|
||||
* Create not conserved group
|
||||
* @returns {L.LayerGroup}
|
||||
*/
|
||||
GIS.notConserved = async function () {
|
||||
let notConserData = await fetch(`${API_URL}/not_conserved`)
|
||||
.then(data => data.json());
|
||||
|
||||
let notConserved = [];
|
||||
|
||||
for (let record of notConserData.records) {
|
||||
notConserved.push(L.marker(
|
||||
record.coordinates,
|
||||
{icon: Icons.notConserved}
|
||||
).bindTooltip(record.denomination)
|
||||
.on(
|
||||
'click',
|
||||
() => UI.openNotConserModal(record, '#not-conser-data')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return L.layerGroup(notConserved);
|
||||
}
|
||||
/*
|
||||
GIS._prepareLayers = async function(layer) {
|
||||
const fromStorage = localStorage.getItem(layer.id);
|
||||
@ -321,7 +322,51 @@ GIS.initLayers = async function(map) {
|
||||
return {baseMap, sitesGroup};
|
||||
}
|
||||
/**
|
||||
* @todo Distinguere tipo di geojson per contenuto popup
|
||||
* Toggle spherical photos on the map
|
||||
* based on zoom level
|
||||
*/
|
||||
GIS.toggleSpherical = async function(map) {
|
||||
// TODO Create points layer
|
||||
const spherical = await this._fetchData('spherical/by/gis/gradola');
|
||||
let sphereMarkers = [];
|
||||
const sPhoto = new SphericalPhoto();
|
||||
|
||||
if (spherical) {
|
||||
for (let pano of spherical) {
|
||||
let marker = L.marker(pano.coordinates, {
|
||||
icon: Icons.camera,
|
||||
});
|
||||
|
||||
marker.bindTooltip('Apri foto sferica');
|
||||
marker.on('click', () => {
|
||||
let modal = document.querySelector('#spherical-modal');
|
||||
let viewer = document.querySelector('#pano-viewer');
|
||||
viewer.innerHTML = '';
|
||||
modal.classList.add('is-active');
|
||||
modal.querySelector('.modal-background').addEventListener('click', () => {
|
||||
modal.classList.remove('is-active');
|
||||
});
|
||||
modal.querySelector('.modal-close').addEventListener('click', () => {
|
||||
modal.classList.remove('is-active');
|
||||
})
|
||||
sPhoto.setViewer(pano.filename);
|
||||
});
|
||||
|
||||
sphereMarkers.push(marker);
|
||||
}
|
||||
}
|
||||
|
||||
let group = L.layerGroup(sphereMarkers);
|
||||
|
||||
map.on('zoomend', () => {
|
||||
if (map.getZoom() >= 19) {
|
||||
group.addTo(map);
|
||||
} else {
|
||||
group.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @param {string} geoJSON
|
||||
* @param {{color, opacity, weight, fillColor, fillOpacity}} options Style options for features
|
||||
* @param {boolean} popup Should the features have a popup?
|
||||
@ -379,6 +424,14 @@ GIS.layerData = async function (layerId) {
|
||||
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* Get spherical photos for a site
|
||||
* @param {int} siteId
|
||||
*/
|
||||
GIS.getSpherical = async function (siteId) {
|
||||
const data = await this._fetchData('spherical/' + siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache data from DB in local storage
|
||||
* for a given layer
|
||||
|
26
webgis/js/icons.js
Normal file
26
webgis/js/icons.js
Normal file
@ -0,0 +1,26 @@
|
||||
// Global leaflet
|
||||
/**
|
||||
* @namespace Icons
|
||||
*/
|
||||
const Icons = {};
|
||||
|
||||
Icons.site = L.icon(
|
||||
{
|
||||
iconUrl: 'img/icons/siti.png',
|
||||
iconSize: [24, 36],
|
||||
iconAnchor: [12, 32],
|
||||
tooltipAnchor: [0, -26],
|
||||
}
|
||||
);
|
||||
Icons.notConserved = L.icon(
|
||||
{
|
||||
iconUrl: 'img/icons/non_conserv.png',
|
||||
iconSize: [24, 36],
|
||||
iconAnchor: [12, 32],
|
||||
tooltipAnchor: [0, -26],
|
||||
}
|
||||
);
|
||||
|
||||
Icons.camera = L.divIcon({className: 'fa fa-2x fa-camera'});
|
||||
|
||||
export default Icons;
|
@ -9,6 +9,8 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
|
||||
map._container.setAttribute('aria-busy', false);
|
||||
|
||||
GIS.toggleSpherical(map);
|
||||
|
||||
UI.addCenterMapControl(map, GIS.CENTER_COORDS, GIS.INIT_ZOOM);
|
||||
UI.toggleMenu('siti');
|
||||
UI.toggleBurger('navbar-burger');
|
||||
|
Loading…
Reference in New Issue
Block a user