Reputation: 534
I'm trying to find a way to display labels on OpenLayers vector features only when the mouse hovers over the feature's icon. I've found a few examples of similar things but nothing that quite does what I need to do. It seems to me like it would be fairly simple but I just can't work out how to start.
This is what my feature style code looks like (one example of several). Note that I'm bringing in the feature data from a few GeoJSON files, hence the feature.get(...)
s in the color sections:
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 { ...
I'm really hoping that there's a way to insert some code into the style definition that creates the hover interaction, rather than having to create a duplicate of every style and then write some extra code that switches between the hover/non-hover styles as necessary. Maybe it could be by way of setting the alpha value in the text color to 255 on mouseover and 0 at other times. Perhaps I'm being too optimistic.
Does anyone have any ideas or examples I could check out?
Thanks, Gareth
EDIT: Thanks to Jose I'm much closer to the goal now. My original code has changed somewhat since I first asked the question. I'm now applying styles to each feature through a function which reads the name of the icon file from GeoJSON data. For example gates are displayed with a 'gate-open' or 'gate-closed' icon and silos with a 'silo-high', 'silo-medium' or 'silo-low' icon. The correct icons and text are displaying on hover for all features, which is great - it's just that when I'm not hovering over the icons, the incorrect icon is displaying - it's showing the 'silo-low' icon for all features. When I hover over an icon it shows the correct icon, then reverts back when I'm no longer hovering.
Here's (the important bits of) my updated code:
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;
});
});
I'm not getting any errors - it's just not showing the correct icon unless the mouse is hovering over the icon.
I'm sure I'm missing something really obvious, but I can't work it out. Any ideas please?
Upvotes: 3
Views: 8039
Reputation: 3683
You can use 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>
Upvotes: 5