Openlayers 悬停渲染顺序,将特征渲染悬停在所有其他特征之上
Openlayers Hover render order, hover feature rendering over all other features
我正在寻找一种仅在该特征上渲染悬停特征向量的方法,实质上是在其特征上渲染悬停向量而不在其他特征上渲染(具体来说,LineString 悬停不在邻近标记上渲染)
我已经根据 vector example 毫无问题地设置了悬停,所有功能都按照我想要的顺序呈现(LineStrings 在标记下方)。问题在于,当 LineString 悬停在其悬停功能上时,不仅会在该 LineString 上呈现,还会在 LineString 穿过的任何标记上呈现,因此 LineString 悬停在该标记上时会出现很大的条纹。考虑到特征叠加向量的工作原理,我可以看出这是多么有意义,但我看不到如何根据需要调整它。
我发现一些帖子似乎提供了关于在样式中设置 zIndex 或使用 renderOrder 函数的不协调建议,尽管 none 似乎完全适用于这种情况,或者超出了我的 n00b 能力.我已经尝试在所有相关样式上设置 zIndex 以及 的内容,但没有达到预期的效果。特别是对于后者,我无法弄清楚将函数放在哪里,以便悬停可以根据它呈现。
非常感谢任何建议!
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: 'map',
view: new ol.View({
center: ol.proj.fromLonLat([132.4903, 34.0024]),
zoom: 4
})
});
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
url: '../static/gpx/summer3.kml',
format: new ol.format.KML({
extractStyles: false
})
}),
style: function(feature) {
return routeStyle;
},
});
vectorLayer.getSource().on('addfeature', function(event) {
event.feature.set('hoverstyle', 'route');
});
map.addLayer(vectorLayer);
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
url: '../static/gpx/testmoo3.kml',
format: new ol.format.KML({
extractStyles: false,
}),
}),
style: function(feature) {
return iconStyle;
},
});
vectorLayer.getSource().on('addfeature', function(event) {
event.feature.set('hoverstyle', 'route');
});
map.addLayer(vectorLayer);
var hoverStyles = {
'moo': new ol.style.Icon({
anchor: [0.5, 30],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: '../static/GPX/icon/mooinb.png',
}),
'route': new ol.style.Stroke({
color: 'rgba(236, 26, 201, 0.5)',
width: 5
})
};
var routeStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'rgba(209,14,14,.6)',
width: 4
})
});
var iconStyle = new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 30],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: '../static/GPX/icon/moo7.png',
}),
});
var hoverStyleCache = {}
function hoverStyler(feature, resolution) {
var hover = feature.get('hoverstyle');
var geometry = feature.getGeometry().getType();
console.log(hover);
while (geometry === 'Point') {
if (!hoverStyleCache[hover]) {
hoverStyleCache[hover] = new ol.style.Style({
image: hoverStyles[hover],
})
}
return [hoverStyleCache[hover]];
}
while (geometry === 'LineString') {
if (!hoverStyleCache[hover]) {
hoverStyleCache[hover] = new ol.style.Style({
stroke: hoverStyles[hover]
})
}
return [hoverStyleCache[hover]];
}
}
var featureOverlay = new ol.layer.Vector({
source: new ol.source.Vector(),
map: map,
style: hoverStyler
});
var highlight;
var hover = function(pixel) {
var feature = map.forEachFeatureAtPixel(pixel, function(feature) {
return feature;
});
if (feature !== highlight) {
if (highlight) {
featureOverlay.getSource().removeFeature(highlight);
}
if (feature) {
featureOverlay.getSource().addFeature(feature);
}
highlight = feature;
}
};
map.on('pointermove', function(evt) {
if (evt.dragging) {
return;
}
var pixel = map.getEventPixel(evt.originalEvent);
hover(pixel);
});
***** 编辑 1 *****
Here is a plunkr that at least illustrates what I mean(悬停矢量与标记重叠)。
我继续摆弄并设法实现了我想要的,通过将点和线串 'featureOverlay' 向量分成两个单独的向量,尽管为了让它工作我还必须复制所有这意味着(hoverStyler 功能、悬停功能等)。
同样,当我在上面提到不协调的建议时,这些建议特别突出,因为我能够在任何矢量图层上设置 zIndex,但不能在样式中设置,就像我在几乎所有其他问题中读到的那样,我找到了向量本身。因此,
var featureOverlay = new ol.layer.Vector({
source: new ol.source.Vector(),
map: map,
style: hoverStyler,
zIndex: 1,
});
有效(将 zIndex 类似地应用于其他矢量图层),但因为点和线串共享特征叠加,这也意味着标记的悬停矢量图像低于它打算悬停的标记:应用于此线串和标记都悬停在上方的方式。
因此我试图想出一个类似于 hoverStyler 的功能来区分它们:
function zIndexer(feature, resolution) {
var geometry = feature.getGeometry().getType();
if (geometry === 'Point') {
return 5
}
if (geometry === 'LineString') {
return 1
}
}
但无济于事(我不确定究竟应该返回什么,并尝试了各种输入;这与其他输入一样无效)。
所以我可以接受重复的 featureOverlay 设备,但是一个方便的 zIndex 函数当然是更好的:)
(*注意:我无法让 zIndex 如上所述在 plunkr 中工作,无论是在 Styles 中还是在 Styles 之外,因此它并没有说明我后来的摆弄,而只是原始问题)
***** 编辑 2 *****
我在下面对提供的答案的评论中指出,虽然答案非常有效,但它确实使集群样式按功能设置样式(原始 post0 中未提及不起作用。我用以下向量克服了这个问题,它工作但我没有资格说工作好:
var clusterCache = {}
var CLM = new ol.layer.Vector({
source: new ol.source.Vector(),
style: function(feature) {
var size = feature.get('features').length;
var style = clusterCache[size]
if (size === 1) {
return [hoverStyles['moo']]
}
else if (size > 1) {
if (!style) {
style = new ol.style.Style({
image:new ol.style.Icon({
anchor: [0.5, 30],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: '../static/GPX/icon/moo3Hover.png',
}),
text: new ol.style.Text({
text: size.toString(),
font: '12px Calibri,sans-serif',
fill: new ol.style.Fill({
color: '#fff'
}),
stroke: new ol.style.Stroke({
color: '#000',
width: 5
}),
offsetX: 22,
offsetY: 6,
})
}),
clusterCache[size] = style;
}
return style;
}
}
});
hoverLayers['clustermoo'] = CLM;
接近
基本思路是您需要为路线和图标(从上到下)单独的悬停层:
- 图标悬停层
- 图标层
- 路线悬停图层
- 路由层
这意味着一个未悬停的图标将绘制在悬停路线的顶部。
ZIndex
您不能使用 zIndex 样式,因为它仅适用于图层中的要素。也就是说,图层 zIndex 的优先级高于样式 zIndex。在你的 plunkr 中,我根本无法让图层 zIndex 工作,但它隐含在添加图层的顺序中。
因此,您需要:
- 创建单独的悬停层
- 按照我上面给出的顺序设置图层
- 悬停要素时,将其移动到适当的悬停层
- 取消悬停要素时,将其从相应的悬停层中移除
样式缓存
另一件事,您的样式缓存实现相当可疑。事实上,您不需要样式缓存,因为您使用的是图层样式,它们只有 assigned/created 一次。
Plunkr
这是经过上述更改的更新插件:https://plnkr.co/edit/gpswRq3tjTTy9O0L
var createHoverLayer = function(style) {
return new ol.layer.Vector({
source: new ol.source.Vector(),
style: style,
});
}
var hoverLayers = {};
hoverLayers['route'] = createHoverLayer([hoverStyles['route']]);
hoverLayers['moo'] = createHoverLayer([hoverStyles['moo']]);
map.addLayer(routeLayer);
map.addLayer(hoverLayers['route']);
map.addLayer(mooLayer);
map.addLayer(hoverLayers['moo']);
var highlight;
var hover = function(pixel) {
var feature = map.forEachFeatureAtPixel(pixel, function(feature) {
return feature;
});
if (feature !== highlight) {
if (highlight) {
var highlightType = highlight.get('type');
hoverLayers[highlightType].getSource().removeFeature(highlight);
}
if (feature) {
var featureType = feature.get('type');
hoverLayers[featureType].getSource().addFeature(feature);
}
highlight = feature;
}
};
替代方法
- 根本不要使用单独的悬停层
- 通过样式函数使用每个特征样式
- 当特征为hovered/unhovered时,在其上设置一个'hovered' 属性
至 true/false
- 在样式函数中,勾选这个属性并使用合适的
风格
- 您将需要使用此方法的样式缓存
我正在寻找一种仅在该特征上渲染悬停特征向量的方法,实质上是在其特征上渲染悬停向量而不在其他特征上渲染(具体来说,LineString 悬停不在邻近标记上渲染)
我已经根据 vector example 毫无问题地设置了悬停,所有功能都按照我想要的顺序呈现(LineStrings 在标记下方)。问题在于,当 LineString 悬停在其悬停功能上时,不仅会在该 LineString 上呈现,还会在 LineString 穿过的任何标记上呈现,因此 LineString 悬停在该标记上时会出现很大的条纹。考虑到特征叠加向量的工作原理,我可以看出这是多么有意义,但我看不到如何根据需要调整它。
我发现一些帖子似乎提供了关于在样式中设置 zIndex 或使用 renderOrder 函数的不协调建议,尽管 none 似乎完全适用于这种情况,或者超出了我的 n00b 能力.我已经尝试在所有相关样式上设置 zIndex 以及
非常感谢任何建议!
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: 'map',
view: new ol.View({
center: ol.proj.fromLonLat([132.4903, 34.0024]),
zoom: 4
})
});
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
url: '../static/gpx/summer3.kml',
format: new ol.format.KML({
extractStyles: false
})
}),
style: function(feature) {
return routeStyle;
},
});
vectorLayer.getSource().on('addfeature', function(event) {
event.feature.set('hoverstyle', 'route');
});
map.addLayer(vectorLayer);
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
url: '../static/gpx/testmoo3.kml',
format: new ol.format.KML({
extractStyles: false,
}),
}),
style: function(feature) {
return iconStyle;
},
});
vectorLayer.getSource().on('addfeature', function(event) {
event.feature.set('hoverstyle', 'route');
});
map.addLayer(vectorLayer);
var hoverStyles = {
'moo': new ol.style.Icon({
anchor: [0.5, 30],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: '../static/GPX/icon/mooinb.png',
}),
'route': new ol.style.Stroke({
color: 'rgba(236, 26, 201, 0.5)',
width: 5
})
};
var routeStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'rgba(209,14,14,.6)',
width: 4
})
});
var iconStyle = new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 30],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: '../static/GPX/icon/moo7.png',
}),
});
var hoverStyleCache = {}
function hoverStyler(feature, resolution) {
var hover = feature.get('hoverstyle');
var geometry = feature.getGeometry().getType();
console.log(hover);
while (geometry === 'Point') {
if (!hoverStyleCache[hover]) {
hoverStyleCache[hover] = new ol.style.Style({
image: hoverStyles[hover],
})
}
return [hoverStyleCache[hover]];
}
while (geometry === 'LineString') {
if (!hoverStyleCache[hover]) {
hoverStyleCache[hover] = new ol.style.Style({
stroke: hoverStyles[hover]
})
}
return [hoverStyleCache[hover]];
}
}
var featureOverlay = new ol.layer.Vector({
source: new ol.source.Vector(),
map: map,
style: hoverStyler
});
var highlight;
var hover = function(pixel) {
var feature = map.forEachFeatureAtPixel(pixel, function(feature) {
return feature;
});
if (feature !== highlight) {
if (highlight) {
featureOverlay.getSource().removeFeature(highlight);
}
if (feature) {
featureOverlay.getSource().addFeature(feature);
}
highlight = feature;
}
};
map.on('pointermove', function(evt) {
if (evt.dragging) {
return;
}
var pixel = map.getEventPixel(evt.originalEvent);
hover(pixel);
});
***** 编辑 1 *****
Here is a plunkr that at least illustrates what I mean(悬停矢量与标记重叠)。
我继续摆弄并设法实现了我想要的,通过将点和线串 'featureOverlay' 向量分成两个单独的向量,尽管为了让它工作我还必须复制所有这意味着(hoverStyler 功能、悬停功能等)。
同样,当我在上面提到不协调的建议时,这些建议特别突出,因为我能够在任何矢量图层上设置 zIndex,但不能在样式中设置,就像我在几乎所有其他问题中读到的那样,我找到了向量本身。因此,
var featureOverlay = new ol.layer.Vector({
source: new ol.source.Vector(),
map: map,
style: hoverStyler,
zIndex: 1,
});
有效(将 zIndex 类似地应用于其他矢量图层),但因为点和线串共享特征叠加,这也意味着标记的悬停矢量图像低于它打算悬停的标记:应用于此线串和标记都悬停在上方的方式。
因此我试图想出一个类似于 hoverStyler 的功能来区分它们:
function zIndexer(feature, resolution) {
var geometry = feature.getGeometry().getType();
if (geometry === 'Point') {
return 5
}
if (geometry === 'LineString') {
return 1
}
}
但无济于事(我不确定究竟应该返回什么,并尝试了各种输入;这与其他输入一样无效)。
所以我可以接受重复的 featureOverlay 设备,但是一个方便的 zIndex 函数当然是更好的:)
(*注意:我无法让 zIndex 如上所述在 plunkr 中工作,无论是在 Styles 中还是在 Styles 之外,因此它并没有说明我后来的摆弄,而只是原始问题)
***** 编辑 2 *****
我在下面对提供的答案的评论中指出,虽然答案非常有效,但它确实使集群样式按功能设置样式(原始 post0 中未提及不起作用。我用以下向量克服了这个问题,它工作但我没有资格说工作好:
var clusterCache = {}
var CLM = new ol.layer.Vector({
source: new ol.source.Vector(),
style: function(feature) {
var size = feature.get('features').length;
var style = clusterCache[size]
if (size === 1) {
return [hoverStyles['moo']]
}
else if (size > 1) {
if (!style) {
style = new ol.style.Style({
image:new ol.style.Icon({
anchor: [0.5, 30],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: '../static/GPX/icon/moo3Hover.png',
}),
text: new ol.style.Text({
text: size.toString(),
font: '12px Calibri,sans-serif',
fill: new ol.style.Fill({
color: '#fff'
}),
stroke: new ol.style.Stroke({
color: '#000',
width: 5
}),
offsetX: 22,
offsetY: 6,
})
}),
clusterCache[size] = style;
}
return style;
}
}
});
hoverLayers['clustermoo'] = CLM;
接近
基本思路是您需要为路线和图标(从上到下)单独的悬停层:
- 图标悬停层
- 图标层
- 路线悬停图层
- 路由层
这意味着一个未悬停的图标将绘制在悬停路线的顶部。
ZIndex
您不能使用 zIndex 样式,因为它仅适用于图层中的要素。也就是说,图层 zIndex 的优先级高于样式 zIndex。在你的 plunkr 中,我根本无法让图层 zIndex 工作,但它隐含在添加图层的顺序中。
因此,您需要:
- 创建单独的悬停层
- 按照我上面给出的顺序设置图层
- 悬停要素时,将其移动到适当的悬停层
- 取消悬停要素时,将其从相应的悬停层中移除
样式缓存
另一件事,您的样式缓存实现相当可疑。事实上,您不需要样式缓存,因为您使用的是图层样式,它们只有 assigned/created 一次。
Plunkr
这是经过上述更改的更新插件:https://plnkr.co/edit/gpswRq3tjTTy9O0L
var createHoverLayer = function(style) {
return new ol.layer.Vector({
source: new ol.source.Vector(),
style: style,
});
}
var hoverLayers = {};
hoverLayers['route'] = createHoverLayer([hoverStyles['route']]);
hoverLayers['moo'] = createHoverLayer([hoverStyles['moo']]);
map.addLayer(routeLayer);
map.addLayer(hoverLayers['route']);
map.addLayer(mooLayer);
map.addLayer(hoverLayers['moo']);
var highlight;
var hover = function(pixel) {
var feature = map.forEachFeatureAtPixel(pixel, function(feature) {
return feature;
});
if (feature !== highlight) {
if (highlight) {
var highlightType = highlight.get('type');
hoverLayers[highlightType].getSource().removeFeature(highlight);
}
if (feature) {
var featureType = feature.get('type');
hoverLayers[featureType].getSource().addFeature(feature);
}
highlight = feature;
}
};
替代方法
- 根本不要使用单独的悬停层
- 通过样式函数使用每个特征样式
- 当特征为hovered/unhovered时,在其上设置一个'hovered' 属性 至 true/false
- 在样式函数中,勾选这个属性并使用合适的 风格
- 您将需要使用此方法的样式缓存