OpenLayers 3:悬停时显示矢量标签
OpenLayers 3: Show vector labels on hover
我正在尝试找到一种方法,仅当鼠标悬停在要素图标上时才在 OpenLayers 矢量要素上显示标签。我发现了一些类似的例子,但没有什么能完全满足我的需要。在我看来它会相当简单,但我不知道如何开始。
这就是我的特征样式代码的样子(几个例子中的一个)。请注意,我从几个 GeoJSON 文件中引入了特征数据,因此颜色部分中的 feature.get(...)
s:
if (feature.get('level_pc') < 35 ) {
var style = new ol.style.Style({
fill: new ol.style.Fill({color: feature.get('shapefill')}),
stroke: new ol.style.Stroke({color: feature.get('shapestroke')}),
image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
anchor: [16, 16],
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
opacity: 0.75,
src: '/icons/aws-red.png'
})),
text: new ol.style.Text({
font: '12px Roboto',
text: feature.get('label'),
fill: new ol.style.Fill({
color: feature.get('textfill')
}),
stroke: new ol.style.Stroke({
color: feature.get('textstroke'),
width: 1
})
})
});
return style
} else { ...
我真的希望有一种方法可以将一些代码插入到创建悬停交互的样式定义中,而不是必须为每个样式创建一个副本,然后编写一些额外的代码在 hover/non-hover 根据需要设置样式。也许可以通过在鼠标悬停时将文本颜色中的 alpha 值设置为 255 而在其他时间设置为 0 来实现。可能是我太乐观了。
有没有人有任何想法或示例可供我查看?
谢谢,
加雷斯
编辑:多亏了何塞,我现在离目标更近了。自从我第一次问这个问题以来,我的原始代码发生了一些变化。我现在通过一个从 GeoJSON 数据读取图标文件名称的函数将样式应用于每个功能。例如,大门显示为 'gate-open' 或 'gate-closed' 图标,筒仓显示为 'silo-high'、'silo-medium' 或 'silo-low' 图标。所有功能都在悬停时显示正确的图标和文本,这很棒 - 只是当我没有将鼠标悬停在图标上时,显示的是不正确的图标 - 它显示所有功能的 'silo-low' 图标。当我将鼠标悬停在某个图标上时,它会显示正确的图标,然后在我不再悬停时恢复原状。
这是我更新后的代码的(重要部分):
var structuresStyleHover = function(feature, resolution) {
style = new ol.style.Style({
fill: new ol.style.Fill({color: feature.get('shapefill')}),
stroke: new ol.style.Stroke({color: feature.get('shapestroke')}),
image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
anchor: [16, 16],
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
opacity: 1,
src: '/icons/'+feature.get('icon')+'-'+feature.get('status').toLowerCase()+'.png'
})),
text: new ol.style.Text({
font: '12px Roboto',
text: feature.get('label'),
fill: new ol.style.Fill({
color: feature.get('textfill')
}),
stroke: new ol.style.Stroke({
color: feature.get('textstroke'),
width: 1
})
})
})
return style;
};
var styleCache = {};
var styleFunction = function(feature,resolution) {
var radius = 16;
var style = styleCache[radius];
if (!style) {
style = new ol.style.Style({
image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
anchor: [16, 16],
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
opacity: 0.5,
src: '/icons/'+feature.get('icon')+'-'+feature.get('status').toLowerCase()+'.png'
})),
});
styleCache[radius] = style;
}
return style;
};
var structuresLayer = new ol.layer.Vector({
source: structuresSource,
style: styleFunction
});
...
var map = new ol.Map({
layers: [paddocksLayer,structuresLayer],
interactions: ol.interaction.defaults({
altShiftDragRotate: false,
dragPan: false,
rotate: false
}).extend([new ol.interaction.DragPan({kinetic: null})]),
target: olMapDiv,
view: view
});
...
map.on('pointermove', function(evt) {
if (evt.dragging) {
return;
}
structuresLayer.getSource().getFeatures().forEach(f=>{
f.setStyle(styleFunction);
});
var pixel = map.getEventPixel(evt.originalEvent);
map.forEachFeatureAtPixel(pixel,function(feature,resolution) {
feature.setStyle(structuresStyleHover(feature,resolution));
return feature;
});
});
我没有收到任何错误 - 它只是没有显示正确的图标,除非鼠标悬停在图标上。
我确定我遗漏了一些非常明显的东西,但我无法解决。有什么想法吗?
您可以使用 setStyle
:
var mystyle = new ol.style.Style({
fill: new ol.style.Fill({color: '#00bbff'}),
stroke: new ol.style.Stroke({color: '#fff'}),
image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
anchor: [16, 16],
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
scale : 0.1,
opacity: 1,
src: 'http://2.bp.blogspot.com/_Sdh3wYnDKG0/TUiIRjXEimI/AAAAAAAAQeU/bGdHVRjwlhk/s1600/map+pin.png'
})),
text: new ol.style.Text({
font: '12px Roboto',
text: 'AAAAAAAAAAAAAAA',
fill: new ol.style.Fill({
color: '#ffbb00'
}),
stroke: new ol.style.Stroke({
color: '#000',
width: 1
})
})
});
var styleCache = {};
var styleFunction = function(feature) {
var radius = 3;
var style = styleCache[radius];
if (!style) {
style = new ol.style.Style({
image: new ol.style.Circle({
radius: radius,
fill: new ol.style.Fill({
color: 'rgba(255, 153, 0, 0.4)'
}),
stroke: new ol.style.Stroke({
color: 'rgba(255, 204, 0, 0.2)',
width: 1
})
})
});
styleCache[radius] = style;
}
return style;
};
var vector = new ol.layer.Vector({
source: new ol.source.Vector({
url: 'http://openlayers.org/en/v3.17.1/examples/data/kml/2012_Earthquakes_Mag5.kml',
format: new ol.format.KML({
extractStyles: false
})
}),
style: styleFunction
});
var raster = new ol.layer.Tile({
source: new ol.source.Stamen({
layer: 'toner'
})
});
var map = new ol.Map({
layers: [raster, vector],
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
map.on('pointermove', function(evt) {
if (evt.dragging) {
return;
}
vector.getSource().getFeatures().forEach(f=>{
f.setStyle(styleFunction);
});
var pixel = map.getEventPixel(evt.originalEvent);
map.forEachFeatureAtPixel(pixel,function(feature) {
feature.setStyle(mystyle);
return feature;
});
});
#map {
position: relative;
}
<title>Earthquakes in KML</title>
<link rel="stylesheet" href="http://openlayers.org/en/v3.17.1/css/ol.css" type="text/css">
<script src="http://openlayers.org/en/v3.17.1/build/ol.js"></script>
<script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<div id="map" class="map"></div>
我正在尝试找到一种方法,仅当鼠标悬停在要素图标上时才在 OpenLayers 矢量要素上显示标签。我发现了一些类似的例子,但没有什么能完全满足我的需要。在我看来它会相当简单,但我不知道如何开始。
这就是我的特征样式代码的样子(几个例子中的一个)。请注意,我从几个 GeoJSON 文件中引入了特征数据,因此颜色部分中的 feature.get(...)
s:
if (feature.get('level_pc') < 35 ) {
var style = new ol.style.Style({
fill: new ol.style.Fill({color: feature.get('shapefill')}),
stroke: new ol.style.Stroke({color: feature.get('shapestroke')}),
image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
anchor: [16, 16],
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
opacity: 0.75,
src: '/icons/aws-red.png'
})),
text: new ol.style.Text({
font: '12px Roboto',
text: feature.get('label'),
fill: new ol.style.Fill({
color: feature.get('textfill')
}),
stroke: new ol.style.Stroke({
color: feature.get('textstroke'),
width: 1
})
})
});
return style
} else { ...
我真的希望有一种方法可以将一些代码插入到创建悬停交互的样式定义中,而不是必须为每个样式创建一个副本,然后编写一些额外的代码在 hover/non-hover 根据需要设置样式。也许可以通过在鼠标悬停时将文本颜色中的 alpha 值设置为 255 而在其他时间设置为 0 来实现。可能是我太乐观了。
有没有人有任何想法或示例可供我查看?
谢谢, 加雷斯
编辑:多亏了何塞,我现在离目标更近了。自从我第一次问这个问题以来,我的原始代码发生了一些变化。我现在通过一个从 GeoJSON 数据读取图标文件名称的函数将样式应用于每个功能。例如,大门显示为 'gate-open' 或 'gate-closed' 图标,筒仓显示为 'silo-high'、'silo-medium' 或 'silo-low' 图标。所有功能都在悬停时显示正确的图标和文本,这很棒 - 只是当我没有将鼠标悬停在图标上时,显示的是不正确的图标 - 它显示所有功能的 'silo-low' 图标。当我将鼠标悬停在某个图标上时,它会显示正确的图标,然后在我不再悬停时恢复原状。
这是我更新后的代码的(重要部分):
var structuresStyleHover = function(feature, resolution) {
style = new ol.style.Style({
fill: new ol.style.Fill({color: feature.get('shapefill')}),
stroke: new ol.style.Stroke({color: feature.get('shapestroke')}),
image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
anchor: [16, 16],
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
opacity: 1,
src: '/icons/'+feature.get('icon')+'-'+feature.get('status').toLowerCase()+'.png'
})),
text: new ol.style.Text({
font: '12px Roboto',
text: feature.get('label'),
fill: new ol.style.Fill({
color: feature.get('textfill')
}),
stroke: new ol.style.Stroke({
color: feature.get('textstroke'),
width: 1
})
})
})
return style;
};
var styleCache = {};
var styleFunction = function(feature,resolution) {
var radius = 16;
var style = styleCache[radius];
if (!style) {
style = new ol.style.Style({
image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
anchor: [16, 16],
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
opacity: 0.5,
src: '/icons/'+feature.get('icon')+'-'+feature.get('status').toLowerCase()+'.png'
})),
});
styleCache[radius] = style;
}
return style;
};
var structuresLayer = new ol.layer.Vector({
source: structuresSource,
style: styleFunction
});
...
var map = new ol.Map({
layers: [paddocksLayer,structuresLayer],
interactions: ol.interaction.defaults({
altShiftDragRotate: false,
dragPan: false,
rotate: false
}).extend([new ol.interaction.DragPan({kinetic: null})]),
target: olMapDiv,
view: view
});
...
map.on('pointermove', function(evt) {
if (evt.dragging) {
return;
}
structuresLayer.getSource().getFeatures().forEach(f=>{
f.setStyle(styleFunction);
});
var pixel = map.getEventPixel(evt.originalEvent);
map.forEachFeatureAtPixel(pixel,function(feature,resolution) {
feature.setStyle(structuresStyleHover(feature,resolution));
return feature;
});
});
我没有收到任何错误 - 它只是没有显示正确的图标,除非鼠标悬停在图标上。
我确定我遗漏了一些非常明显的东西,但我无法解决。有什么想法吗?
您可以使用 setStyle
:
var mystyle = new ol.style.Style({
fill: new ol.style.Fill({color: '#00bbff'}),
stroke: new ol.style.Stroke({color: '#fff'}),
image: new ol.style.Icon(/** @type {olx.style.IconOptions} */ ({
anchor: [16, 16],
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
scale : 0.1,
opacity: 1,
src: 'http://2.bp.blogspot.com/_Sdh3wYnDKG0/TUiIRjXEimI/AAAAAAAAQeU/bGdHVRjwlhk/s1600/map+pin.png'
})),
text: new ol.style.Text({
font: '12px Roboto',
text: 'AAAAAAAAAAAAAAA',
fill: new ol.style.Fill({
color: '#ffbb00'
}),
stroke: new ol.style.Stroke({
color: '#000',
width: 1
})
})
});
var styleCache = {};
var styleFunction = function(feature) {
var radius = 3;
var style = styleCache[radius];
if (!style) {
style = new ol.style.Style({
image: new ol.style.Circle({
radius: radius,
fill: new ol.style.Fill({
color: 'rgba(255, 153, 0, 0.4)'
}),
stroke: new ol.style.Stroke({
color: 'rgba(255, 204, 0, 0.2)',
width: 1
})
})
});
styleCache[radius] = style;
}
return style;
};
var vector = new ol.layer.Vector({
source: new ol.source.Vector({
url: 'http://openlayers.org/en/v3.17.1/examples/data/kml/2012_Earthquakes_Mag5.kml',
format: new ol.format.KML({
extractStyles: false
})
}),
style: styleFunction
});
var raster = new ol.layer.Tile({
source: new ol.source.Stamen({
layer: 'toner'
})
});
var map = new ol.Map({
layers: [raster, vector],
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
map.on('pointermove', function(evt) {
if (evt.dragging) {
return;
}
vector.getSource().getFeatures().forEach(f=>{
f.setStyle(styleFunction);
});
var pixel = map.getEventPixel(evt.originalEvent);
map.forEachFeatureAtPixel(pixel,function(feature) {
feature.setStyle(mystyle);
return feature;
});
});
#map {
position: relative;
}
<title>Earthquakes in KML</title>
<link rel="stylesheet" href="http://openlayers.org/en/v3.17.1/css/ol.css" type="text/css">
<script src="http://openlayers.org/en/v3.17.1/build/ol.js"></script>
<script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<div id="map" class="map"></div>