OpenLayers 4 - 同时显示来自多个 GeoJSON 文件的特征
OpenLayers 4 - Display features from multiple GeoJSON files at same time
我试图在选中或取消选中复选框时显示或隐藏标记。在每个标记上,我想显示一个弹出窗口,其中包含 GeoJSON 文件中包含的信息。
当我只选中一个复选框时,正确的代码块会按预期执行,但是当我同时选中两个复选框时,只会显示最后一个选中框的弹出窗口。在我的代码中,我有两种类型的标记:游泳池和停车场,例如,如果我选中游泳池的框,我的弹出窗口中会显示正确的信息,但如果我也选中停车场的框,则只有停车场弹出窗口中包含的信息是正确的(所有游泳池的弹出窗口都是错误的:只显示 "undefined")...
问题是这两部分没有同时执行!你有什么想法吗?
我的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Affichage correct de la page -->
<title>Markers</title>
<link rel="stylesheet" href="ol/ol.css">
<link rel="stylesheet" href="ol/ol3-layerswitcher.css">
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="ol/ol.js"></script>
<script src="ol/ol3-layerswitcher.js"></script>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.12/css/all.css" integrity="sha384-G0fIWCsCzJIMAVNQPfjH08cyYaUtMwjJwqiRKxxE/rx96Uroj1BtIQ6MLJuheaO9" crossorigin="anonymous">
<link rel="stylesheet" href="sidebar/css/ol3-sidebar.css" />
<script src="sidebar/js/ol3-sidebar.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
</head>
<body>
<div id="map" class="map"></div>
<div id="popup" class="ol-popup">
<a href="#" id="popup-closer" class="ol-popup-closer"></a>
<div id="popup-content"></div>
</div>
<!--Sidemenu-->
<div id="sidebar" class="sidebar collapsed">
<div class="sidebar-tabs">
<ul role="tablist">
<li><a href="#home" role="tab"><i class="fa fa-map-marker"></i></a></li>
</ul>
</div>
<div class="sidebar-content">
<div class="sidebar-pane" id="home">
<h1 class="sidebar-header">
Marqueurs
<span class="sidebar-close"><i class="fa fa-caret-left"></i></span>
</h1>
<br>
<input type="checkbox" id="swimmpool" name="swimmpool" value="swimmpool">
<label for="subscribeNews">Swimming pools</label>
<br><br>
<input type="checkbox" id="parking" name="parking" value="parking">
<label for="subscribeNews">Parkings</label>
</div>
<div class="sidebar-pane" id="profile">
<h1 class="sidebar-header">Profile<span class="sidebar-close"><i class="fa fa-caret-left"></i></span></h1>
</div>
</div>
</div>
<script>
//Layers
var layer1 = new ol.source.TileWMS({
url: '...',
params: {...},
attributions: '...'
});
var layer2 = new ol.source.TileWMS({
url: '...',
params: {...},
attributions: '...'
});
var layer3 = new ol.source.TileWMS({
url: '...',
params: {...},
attributions: '...'
});
//Marker's style
var parkvert = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'image/parking-vert.png'
}))
});
var parkorange = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'image/parking-orange.png'
}))
});
var parkrouge = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'image/parking-rouge.png'
}))
});
var parknoir = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'image/parking-noir.png'
}))
});
var style_swimmpool = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'image/sports-piscine.png'
}))
});
//GeoJSON files
var swimmpoolLayer = new ol.source.Vector({
url: '...',
format: new ol.format.GeoJSON()
});
var parkingLayer = new ol.source.Vector({
url: '...',
format: new ol.format.GeoJSON()
});
var vectorLayer_Swimmpool = new ol.layer.Vector({
source: swimmpoolLayer
});
var vectorLayer_Parking = new ol.layer.Vector({
source: parkingLayer
});
var view = new ol.View({ //paramètres de la map
center: [0, 0],
minZoom: 11,
maxZoom: 19,
zoom: 13
});
//Map
var map = new ol.Map({
layers: [new ol.layer.Group({
title: 'Fonds de carte',
layers: [
new ol.layer.Tile({
title: 'Layer1',
source: layer1,
type: 'base'
}),
new ol.layer.Tile({
title: 'Layer2',
source: layer2,
type: 'base',
visible: false
})
]
}),
new ol.layer.Group({
title: 'Surcouche',
layers: [
new ol.layer.Tile({
title: 'Layer3',
source: layer3,
format: new ol.format.WFS(), //crée une check box
visible: false
})
]
}),
],
target: 'map',
view: view
});
var sidebar = new ol.control.Sidebar({ element: 'sidebar', position: 'left' });
map.addControl(sidebar);
map.addControl(new ol.control.LayerSwitcher());
$('#swimmpool').on('change', function() {
var isChecked = $(this).is(':checked');
if (isChecked) {
map.addControl(vectorLayer_Swimmpool);
vectorLayer_SwimmPool.setStyle(style_swimmpool);
var element = document.getElementById('popup');
var popup = new ol.Overlay({
element: element,
autoPan: true,
offset: [0, -30]
});
map.addOverlay(popup);
var content_element = document.getElementById('popup-content');
var closer = document.getElementById('popup-closer');
closer.onclick = function() {
popup.setPosition(undefined);
closer.blur();
return false;
};
map.on('click', function(evt){
var feature = map.forEachFeatureAtPixel(evt.pixel,
function(feature) {
return feature;
});
if (feature) {
var geometry = feature.getGeometry();
var coord = geometry.getCoordinates();
if(feature.get('name')!=null) {
var content = '<center><h2>' + feature.get('name') + '</h2></center>' + '<br>';
} else {
var content = '<h5>' + 'Aucune information' + '</h5>';
}
if(feature.get('addr:street')!=null) {
content += '<h5>' + '<i>Adresse : </i>' + feature.get('addr:street') + '</h5>';
}
if(feature.get('phone')!=null) {
content += '<h5>' + '<i>Numéro de téléphone : </i>' + feature.get('phone') + '</h5>';
}
if(feature.get('website')!=null) {
content += '<h5>' + '<i>Site internet : </i>' + '</h5>' + '<p>' + feature.get('website') + '</p>';
}
content_element.innerHTML = content;
popup.setPosition(coord);
}
});
} else {
map.removeControl(vectorLayer_Swimmpool);
}
});
var markers = function style(feature, resolution) {
if (feature.get('PLACES') == null) {
return parknoir;
} else if(feature.get('PLACES') <= feature.get('CAPACITE') * 0.05) {
return parkrouge;
} else if(feature.get('PLACES') <= feature.get('CAPACITE') * 0.15){
return parkorange;
} else if(feature.get('PLACES') > feature.get('CAPACITE') * 0.15) {
return parkvert;
}
}
$('#parking').on('change', function() {
var isChecked = $(this).is(':checked');
if (isChecked) {
map.addControl(vectorLayer_Parking);
vectorLayer_Parking.setStyle(markers);
var element = document.getElementById('popup');
var popup = new ol.Overlay({
element: element,
autoPan: true,
offset: [0, -30]
});
map.addOverlay(popup);
var content_element = document.getElementById('popup-content');
var closer = document.getElementById('popup-closer');
closer.onclick = function() {
popup.setPosition(undefined);
closer.blur();
return false;
};
map.on('click', function(evt){
var feature = map.forEachFeatureAtPixel(evt.pixel,
function(feature) {
return feature;
});
if (feature) {
var geometry = feature.getGeometry();
var coord = geometry.getCoordinates();
if(feature.get('NOM')!=null) {
var content = '<center><h2>' + feature.get('NOM') + '</h2></center>' + '<br>';
}
if(feature.get('ADRESSE')!=null) {
content += '<h5>' + '<i>Adresse : </i>' + feature.get('ADRESSE') + '</h5>';
}
if(feature.get('CAPACITE')!=null) {
content += '<h5>' + '<i>Capacité : </i>' + feature.get('CAPACITE') + '</h5>';
}
if(feature.get('PLACES')!=null) {
content += '<h5>' + '<i>Places disponibles : </i>' + feature.get('PLACES') + '<h5>';
}
content_element.innerHTML = content;
popup.setPosition(coord);
}
});
} else {
map.removeControl(vectorLayer_Parking);
}
});
map.on('pointermove', function(e) {
if (e.dragging) {
return;
};
var pixel = map.getEventPixel(e.originalEvent);
var hit = map.hasFeatureAtPixel(pixel);
map.getViewport().style.cursor = hit ? 'pointer' : '';
});
</script>
</body>
</html>
问题是您正在更改相同 div 的 html 内容。第二次设置 content_element.innerHTML="content"
将覆盖第一次设置的内容。如果您注意到上面您已经使用了上面的 +=
因为它不会覆盖内容,它会添加到内容中。我通过在 <div id="popup-content></div>
下方添加另一个 div 解决了同样的问题,将其命名为任何你想要的 <div id="popup-2"></div>
然后你可以在这里发送第二层信息。因此,如果您的第一个复选框未被切换,那么您的第一个 div 将被设置为空 content_element.innerHTML="";
,第二个 div 则相反。 content_element2.innerHTML="";
但如果他们都有信息,那么它就会全部显示出来。
至于评论中的问题,我在我的复选框上使用了切换功能我相信我在另一个问题中向您展示过。
document.getElementById("parcel").addEventListener("click", function(){
if(!toggleparcels){
map.addLayer(layerWFS)
} else {
map.removeLayer(layerWFS)
}
toggleparcels=!toggleparcels
});
window.toggleparcels=true;
然后我 return 不同层的不同结果而不是单独的点击功能。
map.on('click', function(evt){
var feature = map.forEachFeatureAtPixel(evt.pixel,
function(feature, layer) {
if (layer == ssbores || layer == ssdischarge || layer == ssfacility) {
return feature;
}
});
var feature2 = map.forEachFeatureAtPixel(evt.pixel,
function(feature2, layer2){
if (layer2===meters) {
return feature2;
}
});
从那里开始就是 if else 语句,if(feature)
或 if(feature2)
等
我试图在选中或取消选中复选框时显示或隐藏标记。在每个标记上,我想显示一个弹出窗口,其中包含 GeoJSON 文件中包含的信息。
当我只选中一个复选框时,正确的代码块会按预期执行,但是当我同时选中两个复选框时,只会显示最后一个选中框的弹出窗口。在我的代码中,我有两种类型的标记:游泳池和停车场,例如,如果我选中游泳池的框,我的弹出窗口中会显示正确的信息,但如果我也选中停车场的框,则只有停车场弹出窗口中包含的信息是正确的(所有游泳池的弹出窗口都是错误的:只显示 "undefined")...
问题是这两部分没有同时执行!你有什么想法吗?
我的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Affichage correct de la page -->
<title>Markers</title>
<link rel="stylesheet" href="ol/ol.css">
<link rel="stylesheet" href="ol/ol3-layerswitcher.css">
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="ol/ol.js"></script>
<script src="ol/ol3-layerswitcher.js"></script>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.12/css/all.css" integrity="sha384-G0fIWCsCzJIMAVNQPfjH08cyYaUtMwjJwqiRKxxE/rx96Uroj1BtIQ6MLJuheaO9" crossorigin="anonymous">
<link rel="stylesheet" href="sidebar/css/ol3-sidebar.css" />
<script src="sidebar/js/ol3-sidebar.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
</head>
<body>
<div id="map" class="map"></div>
<div id="popup" class="ol-popup">
<a href="#" id="popup-closer" class="ol-popup-closer"></a>
<div id="popup-content"></div>
</div>
<!--Sidemenu-->
<div id="sidebar" class="sidebar collapsed">
<div class="sidebar-tabs">
<ul role="tablist">
<li><a href="#home" role="tab"><i class="fa fa-map-marker"></i></a></li>
</ul>
</div>
<div class="sidebar-content">
<div class="sidebar-pane" id="home">
<h1 class="sidebar-header">
Marqueurs
<span class="sidebar-close"><i class="fa fa-caret-left"></i></span>
</h1>
<br>
<input type="checkbox" id="swimmpool" name="swimmpool" value="swimmpool">
<label for="subscribeNews">Swimming pools</label>
<br><br>
<input type="checkbox" id="parking" name="parking" value="parking">
<label for="subscribeNews">Parkings</label>
</div>
<div class="sidebar-pane" id="profile">
<h1 class="sidebar-header">Profile<span class="sidebar-close"><i class="fa fa-caret-left"></i></span></h1>
</div>
</div>
</div>
<script>
//Layers
var layer1 = new ol.source.TileWMS({
url: '...',
params: {...},
attributions: '...'
});
var layer2 = new ol.source.TileWMS({
url: '...',
params: {...},
attributions: '...'
});
var layer3 = new ol.source.TileWMS({
url: '...',
params: {...},
attributions: '...'
});
//Marker's style
var parkvert = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'image/parking-vert.png'
}))
});
var parkorange = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'image/parking-orange.png'
}))
});
var parkrouge = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'image/parking-rouge.png'
}))
});
var parknoir = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'image/parking-noir.png'
}))
});
var style_swimmpool = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'image/sports-piscine.png'
}))
});
//GeoJSON files
var swimmpoolLayer = new ol.source.Vector({
url: '...',
format: new ol.format.GeoJSON()
});
var parkingLayer = new ol.source.Vector({
url: '...',
format: new ol.format.GeoJSON()
});
var vectorLayer_Swimmpool = new ol.layer.Vector({
source: swimmpoolLayer
});
var vectorLayer_Parking = new ol.layer.Vector({
source: parkingLayer
});
var view = new ol.View({ //paramètres de la map
center: [0, 0],
minZoom: 11,
maxZoom: 19,
zoom: 13
});
//Map
var map = new ol.Map({
layers: [new ol.layer.Group({
title: 'Fonds de carte',
layers: [
new ol.layer.Tile({
title: 'Layer1',
source: layer1,
type: 'base'
}),
new ol.layer.Tile({
title: 'Layer2',
source: layer2,
type: 'base',
visible: false
})
]
}),
new ol.layer.Group({
title: 'Surcouche',
layers: [
new ol.layer.Tile({
title: 'Layer3',
source: layer3,
format: new ol.format.WFS(), //crée une check box
visible: false
})
]
}),
],
target: 'map',
view: view
});
var sidebar = new ol.control.Sidebar({ element: 'sidebar', position: 'left' });
map.addControl(sidebar);
map.addControl(new ol.control.LayerSwitcher());
$('#swimmpool').on('change', function() {
var isChecked = $(this).is(':checked');
if (isChecked) {
map.addControl(vectorLayer_Swimmpool);
vectorLayer_SwimmPool.setStyle(style_swimmpool);
var element = document.getElementById('popup');
var popup = new ol.Overlay({
element: element,
autoPan: true,
offset: [0, -30]
});
map.addOverlay(popup);
var content_element = document.getElementById('popup-content');
var closer = document.getElementById('popup-closer');
closer.onclick = function() {
popup.setPosition(undefined);
closer.blur();
return false;
};
map.on('click', function(evt){
var feature = map.forEachFeatureAtPixel(evt.pixel,
function(feature) {
return feature;
});
if (feature) {
var geometry = feature.getGeometry();
var coord = geometry.getCoordinates();
if(feature.get('name')!=null) {
var content = '<center><h2>' + feature.get('name') + '</h2></center>' + '<br>';
} else {
var content = '<h5>' + 'Aucune information' + '</h5>';
}
if(feature.get('addr:street')!=null) {
content += '<h5>' + '<i>Adresse : </i>' + feature.get('addr:street') + '</h5>';
}
if(feature.get('phone')!=null) {
content += '<h5>' + '<i>Numéro de téléphone : </i>' + feature.get('phone') + '</h5>';
}
if(feature.get('website')!=null) {
content += '<h5>' + '<i>Site internet : </i>' + '</h5>' + '<p>' + feature.get('website') + '</p>';
}
content_element.innerHTML = content;
popup.setPosition(coord);
}
});
} else {
map.removeControl(vectorLayer_Swimmpool);
}
});
var markers = function style(feature, resolution) {
if (feature.get('PLACES') == null) {
return parknoir;
} else if(feature.get('PLACES') <= feature.get('CAPACITE') * 0.05) {
return parkrouge;
} else if(feature.get('PLACES') <= feature.get('CAPACITE') * 0.15){
return parkorange;
} else if(feature.get('PLACES') > feature.get('CAPACITE') * 0.15) {
return parkvert;
}
}
$('#parking').on('change', function() {
var isChecked = $(this).is(':checked');
if (isChecked) {
map.addControl(vectorLayer_Parking);
vectorLayer_Parking.setStyle(markers);
var element = document.getElementById('popup');
var popup = new ol.Overlay({
element: element,
autoPan: true,
offset: [0, -30]
});
map.addOverlay(popup);
var content_element = document.getElementById('popup-content');
var closer = document.getElementById('popup-closer');
closer.onclick = function() {
popup.setPosition(undefined);
closer.blur();
return false;
};
map.on('click', function(evt){
var feature = map.forEachFeatureAtPixel(evt.pixel,
function(feature) {
return feature;
});
if (feature) {
var geometry = feature.getGeometry();
var coord = geometry.getCoordinates();
if(feature.get('NOM')!=null) {
var content = '<center><h2>' + feature.get('NOM') + '</h2></center>' + '<br>';
}
if(feature.get('ADRESSE')!=null) {
content += '<h5>' + '<i>Adresse : </i>' + feature.get('ADRESSE') + '</h5>';
}
if(feature.get('CAPACITE')!=null) {
content += '<h5>' + '<i>Capacité : </i>' + feature.get('CAPACITE') + '</h5>';
}
if(feature.get('PLACES')!=null) {
content += '<h5>' + '<i>Places disponibles : </i>' + feature.get('PLACES') + '<h5>';
}
content_element.innerHTML = content;
popup.setPosition(coord);
}
});
} else {
map.removeControl(vectorLayer_Parking);
}
});
map.on('pointermove', function(e) {
if (e.dragging) {
return;
};
var pixel = map.getEventPixel(e.originalEvent);
var hit = map.hasFeatureAtPixel(pixel);
map.getViewport().style.cursor = hit ? 'pointer' : '';
});
</script>
</body>
</html>
问题是您正在更改相同 div 的 html 内容。第二次设置 content_element.innerHTML="content"
将覆盖第一次设置的内容。如果您注意到上面您已经使用了上面的 +=
因为它不会覆盖内容,它会添加到内容中。我通过在 <div id="popup-content></div>
下方添加另一个 div 解决了同样的问题,将其命名为任何你想要的 <div id="popup-2"></div>
然后你可以在这里发送第二层信息。因此,如果您的第一个复选框未被切换,那么您的第一个 div 将被设置为空 content_element.innerHTML="";
,第二个 div 则相反。 content_element2.innerHTML="";
但如果他们都有信息,那么它就会全部显示出来。
至于评论中的问题,我在我的复选框上使用了切换功能我相信我在另一个问题中向您展示过。
document.getElementById("parcel").addEventListener("click", function(){
if(!toggleparcels){
map.addLayer(layerWFS)
} else {
map.removeLayer(layerWFS)
}
toggleparcels=!toggleparcels
});
window.toggleparcels=true;
然后我 return 不同层的不同结果而不是单独的点击功能。
map.on('click', function(evt){
var feature = map.forEachFeatureAtPixel(evt.pixel,
function(feature, layer) {
if (layer == ssbores || layer == ssdischarge || layer == ssfacility) {
return feature;
}
});
var feature2 = map.forEachFeatureAtPixel(evt.pixel,
function(feature2, layer2){
if (layer2===meters) {
return feature2;
}
});
从那里开始就是 if else 语句,if(feature)
或 if(feature2)
等