Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

373 righe
18 KiB

<?php echo $this->Html->css('/node_modules/ol/ol'); ?>
<?php echo $this->Html->css('/ol-ext/ol-ext.min'); ?>
<?php echo $this->Html->css('jixel_ol'); ?>
<div class="modal fade" id="geocode-results-modal" style="display: none;" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div id="geocode-results-modal-header" class="modal-header">
<h4 class="modal-title"><?= __('Scegli un risultato:') ?></h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div id="geocode-results-modal-body" class="modal-body"></div>
<div id="geocode-results-modal-footer" class="modal-footer justify-content-between"></div>
</div>
</div>
</div>
<div id="olmap" class="olmap"></div>
<div id="jixel-popup" class="jixel-ol-popup">
<div>
<div id="jixel-popup-header"></div>
<a href="#" id="jixel-popup-closer" class="jixel-ol-popup-closer"></a>
</div>
<div id="jixel-popup-content" class="jixel-ol-popup-content"></div>
</div>
<?php if ($tools): ?>
<div id="jixel-tools-element" class="jixel-ol-tools-button ol-unselectable ol-control">
<?php if ($geocoding): ?>
<button type="button" id="jixel-address-button" onclick="geocode(prompt('<?= __('Inserisci un indirizzo o le coordinate (in formato EPSG:4326)') ?>'))">
<i class="fa fa-location-arrow" title="<?= __('Cerca un indirizzo') ?>"></i>
</button>
<?php endif; ?>
<?php if ($point): ?>
<button type="button" id="jixel-point-button" onclick="toggle_tool('point')">
<i class="fa fa-map-marker" title="<?= __('Inserisci un punto in mappa') ?>"></i>
</button>
<?php endif; ?>
<?php if ($polygon): ?>
<button type="button" id="jixel-polygon-button" onclick="toggle_tool('polygon')">
<i class="fa fa-map" title="<?= __('Inserisci un poligono in mappa') ?>"></i>
</button>
<?php endif; ?>
<?php if ($circle): ?>
<button type="button" id="jixel-circle-button" onclick="toggle_tool('circle')">
<i class="fa fa-circle" title="<?= __('Inserisci un cerchio in mappa') ?>"></i>
</button>
<?php endif; ?>
<?php if (($point || $polygon || $circle) && $delete_geometry): ?>
<button type="button" id="jixel-delete-geometry-button" onclick="toggle_tool('delete-geometry')">
<i class="fa fa-trash" title="<?= __('Cancella una geometria') ?>"></i>
</button>
<?php endif; ?>
</div>
<?php endif; ?>
<?php echo $this->Html->script('/node_modules/ol/dist/ol'); ?>
<?php echo $this->Html->script('/ol-ext/ol-ext.min'); ?>
<?php echo $this->Html->script('moment'); ?>
<?php echo $this->Html->script('jixel-primitives'); ?>
<script>
var createLoaderFunction = (vectorSource, layer_url) => {
return (extent, resolution, projection) => {
let proj = projection.getCode();
let url = layer_url + '&srsname=' + proj + '&bbox=' + extent.join(',');
console.log("chiamato loader con url: " + url);
vectorSource.last_request_identifier = Date.now();
makeGetRequest(url, {identifier: vectorSource.last_request_identifier})
.then((response) => {
if (response.identifier == vectorSource.last_request_identifier) {
const result = response.response;
vectorSource.addFeatures(vectorSource.getFormat().readFeatures(result));
}
if (vectorSource.describe_feature_type != undefined) return vectorSource.describe_feature_type;
const layer_url_parts = layer_url.split('GetFeature');
const describe_feature_type_url = layer_url_parts[0] + 'DescribeFeatureType' + layer_url_parts[1];
return makeGetRequest(describe_feature_type_url);
})
.then((describe_feature_type) => {
vectorSource.describe_feature_type = describe_feature_type;
vectorSource.describe_feature_properties = vectorSource.describe_feature_type.featureTypes[0].properties.reduce((acc, property) => {
acc[property.name] = property.localType;
return acc;
}, {});
})
.catch((error) => {
console.log('createLoaderFunction error:');
console.log(error);
vectorSource.removeLoadedExtent(extent);
});
};
};
var createVectorSource = (layer_url) => {
let vectorSource = new ol.source.Vector({
format: new ol.format.GeoJSON(),
strategy: ol.loadingstrategy.bbox,
});
vectorSource.load = function (url) {
console.log("chiamato load con url: " + url);
this.last_request_identifier = Date.now();
makeGetRequest(url, {identifier: this.last_request_identifier})
.then((response) => {
if (response.identifier == this.last_request_identifier) {
const result = response.response;
const chunk = 20; // max numero di elementi per chunk
let to_be_deleted_features_chuncked = [];
this.getFeatures().filter((feature) => {
return result.features.find(new_feature => new_feature.id === feature.getId()) === undefined;
})
.forEach((to_be_deleted_feature, index) => {
let cdf_index = Math.floor(index / chunk);
to_be_deleted_features_chuncked[cdf_index] !== undefined || (to_be_deleted_features_chuncked[cdf_index] = []);
to_be_deleted_features_chuncked[cdf_index].push(to_be_deleted_feature);
});
to_be_deleted_features_chuncked.forEach((chunk, index) => {
setTimeout(() => {
chunk.forEach(feature => this.removeFeature(feature));
}, 1000 * index);
});
this.addFeatures(this.getFormat().readFeatures(result));
}
})
.catch((error) => {
console.log('vectorSource load error:');
console.log(error);
});
};
vectorSource.setLoader(
createLoaderFunction(vectorSource, layer_url)
);
return vectorSource;
};
var createClusteredSource = (vectorSource) => {
return new ol.source.Cluster({
distance: 50,
source: vectorSource,
geometryFunction: (feature) => {
let geometry = feature.getGeometry();
if (geometry.getType() == 'Point') {
return geometry;
}
if (geometry.getType() == 'Polygon') {
return geometry.getInteriorPoint();
}
if (geometry.getType() == 'GeometryCollection') {
let pointGeom = null;
geometry.getGeometries().forEach((geom) => {
if (geom.getType() == 'Point') {
pointGeom = geom;
}
});
return pointGeom;
}
return null;
},
});
};
var styleFunctionGenerator = (style_object) => {
return (feature, resolution) => {
if (style_object == null) {
// se non è previsto uno stile, restituiamo il default:
return new ol.layer.Vector().getStyleFunction()();
}
let size = feature.get('features') != undefined ? feature.get('features').length : 1;
if (size > 1) {
let image = null;
if (style_object.cluster.image.type == 'circle') {
image = new ol.style.Circle({
radius: 20,
stroke: new ol.style.Stroke({
color: style_object.cluster.image.circle.stroke.color,
}),
fill: new ol.style.Fill({
color: style_object.cluster.image.circle.fill.color,
})
});
}
if (style_object.cluster.image.type == 'chart') {
let data = [];
let colors = [];
style_object.cluster.image.chart.sections.forEach((section) => {
data.push(feature.get('features').filter((feature) => { return section.data.values.includes(feature.get(section.data.field)); }).length);
colors.push(ol.color.asString(section.color));
});
image = new ol.style.Chart({
type: style_object.cluster.image.chart.type,
radius: 20,
data: data,
colors: colors,
rotateWithView: true,
stroke: new ol.style.Stroke({
color: style_object.cluster.image.chart.stroke.color,
width: style_object.cluster.image.chart.stroke.width,
}),
});
}
return new ol.style.Style({
image: image,
text: new ol.style.Text({
text: size.toString(),
font: '12px sans-serif',
fill: new ol.style.Fill({
color: style_object.cluster.text.fill.color,
}),
backgroundFill: new ol.style.Fill({
color: style_object.cluster.text.backgroundFill.color,
}),
}),
});
} else {
// se il layer è clusterizzato: recuperiamo la feature originale che è l'unica attaccata all'array features!
// altrimenti prendiamo direttamente la feature passata
const feature_for_style = feature.get('features') == undefined ? feature : feature.get('features')[0];
// se nello style_object passato è definito un filtro, recuperiamo il campo, il valore e quindi
// lo stile (al momento solo il color indicizzato dal valore del campo configurato)
if (style_object.filter != undefined) {
const filter_field_value = feature_for_style.get(style_object.filter.field);
const filter_color = style_object.filter.values[filter_field_value].color;
if (filter_color != undefined) {
style_object.fill.color = filter_color;
style_object.image.fill.color = filter_color;
}
}
return new ol.style.Style({
geometry: (feature) => {
return feature_for_style.getGeometry();
},
fill: new ol.style.Fill({
color: style_object.fill.color,
}),
stroke: new ol.style.Stroke({
color: style_object.stroke.color,
}),
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: style_object.image.stroke.color,
}),
fill: new ol.style.Fill({
color: style_object.image.fill.color,
})
}),
});
}
}
};
var selectedStyleFunctionGenerator = () => {
return (feature, resolution) => {
let size = feature.get('features') != undefined ? feature.get('features').length : 1;
if (size > 1) {
return new ol.style.Style({
image: new ol.style.Circle({
radius: 20,
stroke: new ol.style.Stroke({
color: [255, 255, 255, 1],
}),
fill: new ol.style.Fill({
color: [0, 0, 255, 0.8],
})
}),
text: new ol.style.Text({
text: size.toString(),
font: '12px sans-serif',
fill: new ol.style.Fill({
color: [255,255,255,1],
})
})
});
} else {
return new ol.style.Style({
geometry: (feature) => {
// se il layer è clusterizzato: recuperiamo la geometria originale che è l'unica attaccata all'array features!
// altrimenti prendiamo la geometria della feature passata
let feature_for_style = feature.get('features') == undefined ? feature : feature.get('features')[0];
return feature_for_style.getGeometry();
},
fill: new ol.style.Fill({
color: [0, 0, 255, 0.8],
}),
stroke: new ol.style.Stroke({
color: [255,255,255,1],
}),
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: [255,255,255,1],
}),
fill: new ol.style.Fill({
color: [0, 0, 255, 0.8],
})
}),
});
}
};
};
var createLayer = (layer_info) => {
let vector_source = createVectorSource(layer_info.url_layer);
if (layer_info.clusterize) {
vector_source = createClusteredSource(vector_source);
}
const layer = new ol.layer.Vector({
id: layer_info.id,
code: layer_info.code,
name: layer_info.name,
url_layer: layer_info.url_layer,
clusterized: layer_info.clusterize,
visible: layer_info.visible,
source: vector_source,
style: styleFunctionGenerator(layer_info.style), // generiamo la style function per le features
zoom_to_layer: layer_info.zoom_to_layer,
});
layer.buildCQLFilter = function (...conditions) {
let valid_conditions = [];
conditions.forEach((condition) => {
typeof condition !== 'string' || condition.length === 0 || (valid_conditions.push(condition));
});
console.log('buildCQLFilter received conditions:');
console.log(conditions);
console.log('buildCQLFilter valid_conditions:');
console.log(valid_conditions);
cql_filter = valid_conditions.length > 0 ? encodeURI('query_filter=' + valid_conditions.join(' AND ')) : '';
console.log('buildCQLFilter returned cql_filter:');
console.log(cql_filter);
return cql_filter;
}
layer.set_layer_source_url = function (url, append, soft) {
let new_url = undefined;
if (typeof url != 'string' || url.length == 0) {
new_url = this.get('url_layer'); // se non passiamo url, ripristiniamo la default
} else {
const append_url = (typeof append == 'boolean') ? append : false;
// creiamo la nuova url come default + '&' + url o come url:
new_url = append_url ? (this.get('url_layer') + '&' + url) : url;
}
const vector_source = this.get('clusterized') ? this.getSource().getSource() : this.getSource();
vector_source.setLoader(createLoaderFunction(vector_source, new_url));
if (typeof soft === 'boolean' && soft) {
vector_source.load(new_url); // eliminiamo le vecchie features e aggiungiamo le nuove in maniera soft (nessun glitch) ma molto + lento!
} else {
vector_source.refresh(); // forziamo il reload delle features dal server
}
console.log("set_layer_source_url:");
console.log(new_url);
return this;
};
return layer;
}
var generatePopupEntryFromFeature = (feature, describe_feature_properties) => {
// non inseriamo nel popup alcune proprietà "speciali"
const popup_mask_keys = ["geometry"];
let body = '<br>';
feature.getKeys().forEach((key) => {
if (!popup_mask_keys.includes(key) && !key.startsWith("hidden_") && feature.get(key) != null) {
const property_type = describe_feature_properties[key];
let key_name = key.ununderscore();
if (property_type == 'date-time' || property_type == 'date') {
let format = property_type == "date-time" ? "DD/MM/YYYY HH:mm" : "DD/MM/YYYY";
let date = property_type == "date-time" ? feature.get(key) : feature.get(key).split('Z')[0];
body += '<b>' + key_name + ':</b> ' + moment.utc(date).format(format) + '<br>';
} else {
body += '<b>' + key_name + ':</b> ' + feature.get(key) + '<br>';
}
}
});
return body + '<hr>';
};
</script>