Meanwhile, I have found a solution. You can see it here:
https://gispublic.stadt-ibb.de/xplanung/dist/
CSS:
@import "node_modules/ol/ol.css";
@import "node_modules/ol-ext/dist/ol-ext.css";
@import "node_modules/ol-ext/overlay/Popup.css";
html, body {
margin: 0;
height: 100%;
font-family:Verdana, Geneva, sans-serif;
font-size: 1em;
}
#map {
position: relative;
float:left;
top: 0;
bottom: 0;
height:80%;
width: 100%;
}
.container{
}
.hinweis {
float:left;
top: 0; /* Ganz oben */
left: 0; /* Ganz links */
font-size:0.7em;
width: 60%; /* Volle Breite */
}
.treffer {
float: left;
top: 0; /* Ganz oben */
left: 0; /* Ganz links */
font-size:0.9em;
width: 30%; /* Volle Breite */
}
.info {
left: 5px; /* Ganz links */
height:1.4em;
}
.options {
font-size:0.9em;
position: absolute;
border-radius: 14px;
padding:6px;
left:10px;
bottom:120px;
width: 250px;
height: 320px;
background-color: white;
z-index:1;
border-width: 3px;
border-style: solid;
border-radius: 0.375rem;
border-color: #dee2e6;
}
.ol-okk {
margin:10px !important;
}
.ol-control.ol-select
{
display:none !important;
}
.ol-popup h1 {
font-size: 1em;
background-size: 2em;
padding-left: 3em;
}
#suche_auffrischen {
background-color:#13c023;
padding:5px;
font-size:0.9em;
}
#suche_auffrischen:hover {
background-color:#5eb566;
}
#suche_auffrischen2 {
background-color:#13c023;
padding:5px;
font-size:0.9em;
}
#suche_auffrischen2:hover {
background-color:#5eb566;
}
JS:
import Map from 'ol/Map.js';
import LayerSwitcher from "ol-ext/control/LayerSwitcher"
import Select from "ol-ext/control/Select.js"
/*import SearchFeature from 'ol-ext/control/SearchFeature.js';
import SelectMulti from 'ol-ext/control/SelectMulti.js';
import SelectFulltext from 'ol-ext/control/SelectFulltext.js';
import SelectPopup from 'ol-ext/control/SelectPopup.js';
import SelectCheck from 'ol-ext/control/SelectCheck.js';
import SelectCondition from 'ol-ext/control/SelectCondition.js';*/
import PopupFeature from "ol-ext/overlay/PopupFeature.js"
import MultiPoint from 'ol/geom/MultiPoint.js';
import Point from 'ol/geom/Point.js';
import CircleStyle from 'ol/style/Circle.js';
import {boundingExtent} from 'ol/extent';
import {getCenter} from 'ol/extent';
//import Control from 'ol/control/Control.js';
import VectorSource from 'ol/source/Vector.js';
import VectorLayer from 'ol/layer/Vector.js';
import {singleClick} from 'ol/events/condition.js';
import Selecti from "ol/interaction/Select.js"
import View from 'ol/View.js';
import {easeIn, easeOut} from 'ol/easing.js';
import TileLayer from 'ol/layer/Tile.js';
import {fromLonLat} from 'ol/proj.js';
import OSM from 'ol/source/OSM.js';
import GeoJSON from 'ol/format/GeoJSON.js';
import Fill from 'ol/style/Fill.js';
import Icon from 'ol/style/Icon.js';
import Stroke from 'ol/style/Stroke.js';
import Style from 'ol/style/Style.js';
import RegularShape from 'ol/style/RegularShape.js';
import ImageLayer from 'ol/layer/Image.js';
import ImageSource from 'ol/source/Image.js';
import {createLoader} from 'ol/source/wms.js';
import ImageWMS from 'ol/source/ImageWMS.js';
import {defaults as defaultControls} from 'ol/control/defaults.js';
import ScaleLine from 'ol/control/ScaleLine.js';
const ibben = fromLonLat([7.716052,52.274762]);
const gruendken = fromLonLat([7.7945,52.2691]);
const kloster = fromLonLat([7.7154,52.2741]);
const tecklenburger_ost = fromLonLat([7.7305,52.2604]);
const nutzungsart = document.getElementById('nutzungsart');
const wmsSource = new ImageWMS({
url: 'https://gispublic.stadt-ibb.de/cgi-bin/qgis_mapserv.fcgi?MAP=/home/qgis/projects/xplanung/xplanung.qgs',
params: {'LAYERS': 'baugebiet_gesamt,Gründkenliet_Nord,Klosterstraße,Tecklenburger_Damm_Ost'},
ratio: 1,// serverType: 'mapserver',
});
const wmsSource2 = new ImageWMS({
url: 'https://gispublic.stadt-ibb.de/cgi-bin/mapserv?map=XPLANUNG',
params: {'LAYERS': 'teilflaechen'},
ratio: 1,
serverType: 'mapserver',
});
const wmsLayer = new ImageLayer({
title: 'Bebauungspläne',
source: wmsSource,
});
const wmsSourceLubi = new ImageWMS({
url: 'https://www.wms.nrw.de/geobasis/wms_nw_dop',
params: {'LAYERS': 'nw_dop_rgb'},
ratio: 1,// serverType: 'mapserver',
});
const wmsLayerLubi = new ImageLayer({
title: 'Luftbild',
source: wmsSourceLubi,
visible: false,
});
const view = new View({
center: ibben,
zoom: 11,
});
const map = new Map({
target: 'map',
controls: defaultControls().extend([
new ScaleLine({
units: 'metric',
}),
]),
layers: [
new TileLayer({
name: 'Hintergrundkarte',
preload: 4,
source: new OSM()
}),wmsLayerLubi,wmsLayer
],
view: view,
});
const switcher = new LayerSwitcher;
// You can add it to the map
map.addControl(switcher)
function onClick(id, callback) {
document.getElementById(id).addEventListener('click', callback);
}
onClick('pan-to-gruendken', function () {
view.animate({
center: gruendken,
zoom: 16,
duration: 2000,
});
});
onClick('pan-to-kloster', function () {
view.animate({
center: kloster,
zoom: 18,
duration: 2000,
});
});
onClick('pan-to-tecklenburger_ost', function () {
view.animate({
center: tecklenburger_ost,
zoom: 16,
duration: 2000,
});
});
//Attributabfrage per WMS
/*
map.on('singleclick', function (evt) {
document.getElementById('info').innerHTML = '</br>';
const viewResolution = view.getResolution();
const url = wmsSource2.getFeatureInfoUrl(
evt.coordinate,
viewResolution,
'EPSG:3857',
{'INFO_FORMAT': 'text/html'},
);
if (url) {
fetch(url)
.then((response) => response.text())
.then((html) => {
document.getElementById('info').innerHTML = html;
});
}
}); */
map.on('pointermove', function (evt) {
if (evt.dragging) {
return;
}
const data = wmsLayer.getData(evt.pixel);
const hit = data && data[3] > 0;
map.getTargetElement().style.cursor = hit ? 'pointer' : '';
});
var vectorSource = new VectorSource({
url: '../xplanung.geojson',
format: new GeoJSON()
});
const styles = [
new Style({
/* stroke: new Stroke({
color: 'black',
width: 1,
}),*/
fill: new Fill({
color: 'rgba(0, 0, 255, 0.0)',
}),
}),
];
map.addLayer(new VectorLayer({
name: 'Suchergebnisse',
source: vectorSource,
style: styles,
}));
const selectStyle=new Style({
stroke: new Stroke({ color: [255,128,0], width:15 }),
fill: false,
/* image: new RegularShape({
radius:35,
points: 35,
fill: new Fill({ color: [255,128,0,.6] }),
stroke: new Stroke({ color: [255,128,0], width:9 })
})*/
})
const selectStyle2=new Style({
stroke: new Stroke({ color: [0,0,255], width:3 }),
fill: null,
})
//Style mit Symbol für Fläche
const selectStyle3= new Style({
image: new Icon({
src: "../b.png",
width: 25,
height:25
}),
geometry: function (feature) {
const coordinates = feature.getGeometry().getInteriorPoints().getPoint(0).getCoordinates();
return new Point(coordinates);
},
})
//Suche zeige.....
// ******************************************************************************************************Select interaction
//Setzt Filter auf Basis der Suchstrings, ermittelt Extent
function setzeFilter(wert) {
const meineFilter = [];
meineFilter.length = 0;
if (flaeche.value !=''){
meineFilter.push({attr: "flaeche", op: ">=", val:flaeche.value });
}
if (gfz.value !=''){
meineFilter.push({attr: "gfz", op: ">=", val:gfz.value });
}
if (grz.value !=''){
meineFilter.push({attr: "grz", op: ">=", val:grz.value });
}
if (nutzungsart.value !=''){
meineFilter.push({attr: "allgartnutztxt", op: "=", val:nutzungsart.value });
}
document.getElementById('treffer').innerHTML='';
var a= selectCtrl.doSelect({conditions:meineFilter});
const anzahlObjekte = Object.keys(a).length;
document.getElementById('treffer').innerHTML='Insgesamt wurde/n '+anzahlObjekte+' Objekt/e gefunden.';
if (anzahlObjekte==0){
return;
}
//Ermittlung der gefilterten FEatures
var sources = selectCtrl.getSources();
sources.forEach(function (s) {
var meineFeatures= selectCtrl._selectFeatures(a, s.getFeatures(), meineFilter, true,true);
const coords = meineFeatures.map((f) => {
const polygon = f.getGeometry();
return polygon.getExtent();
});
const extentx = boundingExtent(coords);
extentx[0]=extentx[0]-500;
extentx[3]=extentx[3]+500;
var extentCoords = [
[
extentx[0]-1400,
extentx[1]
],
[
extentx[2]+1400,
extentx[3]
]
];
var extentNeu = boundingExtent(extentCoords);
//setViewExtent(extent);
if (wert!=0){
map.getView().fit(extentNeu, {duration: 2000});
}
});
}
nutzungsart.addEventListener('input', function () {
setzeFilter();
// selectCtrl.addCondition( {attr: "allgartnutztxt", op: "=", val:nutzungsart.value });
});
flaeche.addEventListener('input', function () {
setzeFilter();
//var waslos=selectCtrl.getConditions();
//alert (JSON.stringify(waslos));
});
gfz.addEventListener('input', function () {
setzeFilter();
// selectCtrl.addCondition( {attr: "allgartnutztxt", op: "=", val:nutzungsart.value });
});
grz.addEventListener('input', function () {
setzeFilter();
// selectCtrl.addCondition( {attr: "allgartnutztxt", op: "=", val:nutzungsart.value });
});
// Select control
var selecti = new Selecti({
hitTolerance: 5,
style:selectStyle2,
condition: singleClick
});
map.addInteraction(selecti);
//Attributsuche
var selectCtrl = new Select({
source: vectorSource,
addLabel: "Suche absenden",
property: $(".options select").val()
});
selectCtrl.on('select', function(e) {
selecti.getFeatures().clear();
for (var i=0, f; f=e.features[i]; i++) {
selecti.getFeatures().push(f);
f.setStyle(selectStyle);
}
});
//******************************************************************************************************************************
//Darstellung von Infos in Popup
var popup = new PopupFeature({
popupClass: 'default anim',
select: selecti,
canFix: true,
template: {
title:
// 'nom', // only display the name
function(f) {
return "Id: "+f.get('fid')+' ('+f.get('gebiet')+')';
},
attributes: // [ 'region', 'arrond', 'cantons', 'communes', 'pop' ]
{
'allgartnutztxt': { title: 'Allgemeine Art der Nutzung:' },
'besartnutztxt': { title: 'Besondere Art der Nutzung:' },
'flaeche': { title: 'Fläche (m²):' },
'gfz': { title: 'GFZ:' },
'grz': { title: 'GRZ:' },
}
}
});
map.addOverlay (popup);
onClick('suche_auffrischen', function () {
setzeFilter();
});
onClick('suche_auffrischen2', function () {
setzeFilter(0);
});