I have some troubles with z-index on OpenLayers 3 when i want to highlight a feature.
I create a GeoJSON shape of a country, add some marker on top, and i want the shape color change when i hover on.
But, when the color change, the shape hide my markers.
I try to put zIndex style on the hightlight style but this doesn't change anything...
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})],
controls: ol.control.defaults({
attributionOptions: ({
collapsible: false
})
}),
target: 'map',
view: new ol.View({
center: [631965.84, 4918890.2],
zoom: 3
})
});
var vector = new ol.layer.Vector({
source: new ol.source.Vector({}),
style: new ol.style.Style({
zIndex: 1,
stroke: new ol.style.Stroke({
color: '#589CA9',
width: 3
}),
fill: new ol.style.Fill({
color: '#589CA9'
})
})
});
map.addLayer(vector);
var selectPointerMove = new ol.interaction.Select({
condition: ol.events.condition.pointerMove,
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#EF7F01',
width: 3
}),
zIndex: 1,
fill: new ol.style.Fill({
color: '#EF7F01'
})
})
});
map.addInteraction(selectPointerMove);
var feature = new ol.format.GeoJSON().readFeature(Some_GeoJSON_Coordinate, {
dataProjection: ol.proj.get('EPSG:4326'),
featureProjection: ol.proj.get('EPSG:3857')
});
vector.getSource().addFeature(feature);
iconFeature = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.transform([5, 44],"EPSG:4326", 'EPSG:3857')),
type:"marker"
});
var iconStyle = new ol.style.Style({
zIndex:2,
image: new ol.style.Icon(/** #type {olx.style.IconOptions} */ ({
anchor:[0.5,1],
scale:0.1,
src: 'https://lh4.ggpht.com/Tr5sntMif9qOPrKV_UVl7K8A_V3xQDgA7Sw_qweLUFlg76d_vGFA7q1xIKZ6IcmeGqg=w300'
}))
});
iconFeature.setStyle(iconStyle);
vector.getSource().addFeature(iconFeature)
I create a JSFiddle of my issue : http://jsfiddle.net/a1zb5kzf/1/
Thanks you in advance for your help
I found a solution.
According to the Select Interaction documentation, it's don't just apply an other Style but move your feature on a temporary overlay. And so, zIndex doesn't work because features aren't on the same layer anymore.
So, to get my highlight comportement and keep my feature on the same layer, i watch the pointermove event, and apply style if necessary. Just before, i memorized the feature, and reapply default style on it
cartoCtrl.map.on("pointermove", function (evt) {
var feature = cartoCtrl.map.forEachFeatureAtPixel(evt.pixel,
function (feature) {
return feature;
});
if (feature && feature.getProperties().type != "marker") {
cartoCtrl.lastHighlitedFeature = feature;
feature.setStyle(highlightStyle)
}));
} else {
if(cartoCtrl.lastHighlitedFeature){
cartoCtrl.lastHighlitedFeature.setStyle(defautlStyle);
cartoCtrl.lastHighlitedFeature = false;
}
}
});
Related
Following the examples on Openlayers.org I created a point vector layer (with overlays etc.). The points are displayed as cluster points as in the example here:
Openlayers Cluster Example
Now, I need to filter the points according to their properties, e.g. lab_data = 'yes', sampling_year > 1990. The filtering affects the number of points inside the clusters.
I have so far not found a method to exclude features from my Source or Layer objects. I was even unsuccesful in accessing the features and their properties. From there on I could build loops and conditions.
Does anyone maybe have an idea how it is done?
// Read GeoJson point locations
var pointLocations = new ol.source.Vector({
url: 'data/samplingLocations.json',
format: new ol.format.GeoJSON()
});
// create point cluster
var pointCluster = new ol.source.Cluster({
distance: 50,
source: pointLocations
});
// create simple style for single points and clusters
var getStyle = function(feature) {
var length = feature.get('features').length;
if (length > 1) {
style = new ol.style.Style({
image: new ol.style.Circle({
radius: 20,
fill: new ol.style.Fill({ color: "red" }),
}),
})
} else {
style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({ color: "black" }),
}),
})
}
return style;
};
// create a vector layer
var vectorLayer = new ol.layer.Vector({
id: "points",
source: pointCluster,
style: getStyle
});
// create the map
var map = new ol.Map({
layers: [vectorLayer],
target: 'map',
view: new ol.View({
center: [895571,5911157],
zoom: 8,
})
});
So far some of my unsuccessful attempts to access the properties:
console.log( pointLocations.getSource().getFeatures()[0].getProperties().values)
console.log( vectorLayer.getSource().getFeatures()[0].get('values') )
Every help is kindly appreciated!
You can filter with a geometry function, for example:
var pointCluster = new ol.source.Cluster({
distance: 50,
source: pointLocations,
geometryFunction: function(feature) {
if (feature.get('lab_data') == 'yes' && feature.get('sampling_year') > 1990) {
return feature.getGeometry();
} else {
return null;
}
}
});
I am Using Open layers to publish a Map. But I can't figure out the way to Make the map size dynamic according to Screen Size. As the map remains same on every screen irrespective of the screen size. I also tried map.updatesize(). But that is not working too.
My Code is
layer = new ol.layer.Tile({
title: 'Basemap',
baseLayer: true,
visible: true,
source: new ol.source.TileWMS({
url: 'http://mlinfomaps.in/geoserver/wms',
params: { 'LAYERS': 'MSSDS_WS:MSSDS_BASEMAP', 'TILED': true },
serverType: 'geoserver',
// Countries have transparency, so do not fade tiles:
transition: 0,
crossOrigin: "anonymous"
})
});
var mousePositionControl = new ol.control.MousePosition({
coordinateFormat: ol.coordinate.createStringXY(4),
projection: 'EPSG:4326',
// comment the following two lines to have the mouse position
// be placed within the map.
//className: 'custom-mouse-position',
target: document.getElementById('mouse-position'),
//undefinedHTML: ' '
});
var projection = new ol.proj.Projection({
//code: 'EPSG: 4326', // *code says: 5261 ...try to see if this is right
//extent: [71.6142, 22.3645, 81.8754, 15.1508],
extent:[7970828.0670139585, 1681517.1260521673, 9127778.927138386, 2541280.8202038296]
})
function scaleControl() {
control = new ol.control.ScaleLine({
units: 'metric',
bar: true,
steps: 4,
text: true,
minWidth: 100
});
return control;
}
var sourceMeasure = new ol.source.Vector({
crossOrigin: "anonymous",
});
var vectorMeasure = new ol.layer.Vector({
source: sourceMeasure,
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.2)'
}),
stroke: new ol.style.Stroke({
color: '#df1c29',
width: 2
}),
image: new ol.style.Circle({
radius: 6,
fill: new ol.style.Fill({
color: '#df1c29'
})
})
}),
title: 'Measure Overlay',
});
// The Map
//var overlay = new ol.Overlay
// ({
// element: container,
// autoPan: true,
// autoPanAnimation: {
// duration: 250
// }
// });
var view = new ol.View
({
center: ol.proj.transform([76.7997, 18.6298], 'EPSG:4326','EPSG:3857'),
zoom: 7,
extent: projection.getExtent(),
//minZoom:7,
maxZoom: 12
});
var map = new ol.Map
({
target: 'map',
controls: ol.control.defaults().extend([mousePositionControl, scaleControl()]),
view: view,
//fit: view.fit(),
//overlays: [overlay],
layers: [layer]
});
const extent = projection.getExtent()
map.getView().fit(extent);
map.updateSize();
window.onresize = function()
{
setTimeout( function() { map.updateSize();}, 200);
}
'''
The map on different screen looks like this:
On my screen It looks like
https://i.stack.imgur.com/KIYio.png
On my colleague's screen it looks like
https://i.stack.imgur.com/6c4zk.png
Please Help me get through this.
Thanks In Advance!
hello i have the same problem and I solove it by doing that
ts:
html :
I use OpenLayers v6.3.1, including the following stylesheet and script: Scriptfile, Stylesheet
Goal:
My goal is to change the color of a feature (LineString) on runtime using javascript.
Setup:
I mainly used the code from this website: OpenLayers
var map = new ol.Map({
target: 'map', //<div id="map"></div>
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
projection: 'EPSG:4326',
center: [11.592581, 47.241524],
zoom: 15
})
});
In this piece of code I create a line between two coordinates:
var lonlat1 = [11.592581, 47.241524];
var lonlat2 = [11.58554, 47.248958];
//create the line's style
var lineStyle = [
// linestring
new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#000',
width: 2
})
})
];
//create the line
var line = new ol.layer.Vector({
source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.LineString([lonlat1, lonlat2])
})
]
}),
style: lineStyle
});
map.addLayer(line);
Which gives me this map:
I want to change the color of the line at runtime.
What I tried so far:
I tried to change the color using the following code:
line.style_[0].stroke_.color_ = '#123';
The value of the color did change, but the color of the line itself remains the same.
OK, i figured it out. The style can be changed with the setStyle() function which is part of the line object.
line.setStyle([
new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#123',
width: 2
})
})
]);
This is definitely not the best solution so I am open to anything better.
I am trying to display a map with markers. I want the ability to click these markers such that extra information can be displayed (similiar to the way it works in google earth). I have the map and the markers (or features) but can not get the "popup" with extra information to work.
The JS:
function init(){
var northSeaLonLat = [4.25, 52.05];
var centerWebMercator = ol.proj.fromLonLat(northSeaLonLat);
var tileLayer = new ol.layer.Tile({ source: new ol.source.OSM() });
markerLayer = new ol.layer.Vector({ source: new ol.source.Vector({ features: [], projection: 'EPSG:3857' }) });
var map = new ol.Map({
controls: ol.control.defaults().extend([
new ol.control.MousePosition({
coordinateFormat: ol.coordinate.createStringXY(3),
projection: 'EPSG:4326',
undefinedHTML: ' ',
className: 'custom-mouse-position',
target: document.getElementById('custom-mouse-position'),
})
]),
layers: [tileLayer, markerLayer],
target: 'map',
view: new ol.View({
projection: 'EPSG:3857',
center: centerWebMercator,
zoom: 7
})
});
// Add marker
var circle = new ol.style.Style({
image: new ol.style.Circle({
radius: 4,
fill: new ol.style.Fill({
color: 'rgba(200,0,0,0.9)',
}),
stroke: new ol.style.Stroke({
color: 'rgba(100,0,0,0.9)',
width: 2
})
})
});
coordinates = [[4.25, 52.05], [4.21, 52.01], [4.29, 52.29], [5.25, 52.05], [4.25, 51.05]];
for (i = 0; i < coordinates.length; i++) {
var feature = new ol.Feature(
new ol.geom.Point(ol.proj.transform(coordinates[i], 'EPSG:4326', 'EPSG:3857'))
);
feature.description = 'Coordinates: '+coordinates[i][0]+','+coordinates[i][1]+'\nBla';
feature.setStyle(circle);
markerLayer.getSource().addFeature(feature);
}
var element = document.getElementById('popup');
var popup = new ol.Overlay({
element: element,
positioning: 'bottom-center',
stopEvent: false
});
map.addOverlay(popup);
// display popup on click
map.on('click', function(evt) {
var feature = map.forEachFeatureAtPixel(evt.pixel,
function(feature, layer) {
return feature;
});
if (feature) {
popup.setPosition(evt.coordinate);
$(element).popover({
'placement': 'top',
'html': true,
'content': feature.get('description')
});
$(element).popover('show');
} else {
$(element).popover('destroy');
}
});
}
The code I got from an example on the website: http://openlayers.org/en/v3.11.1/examples/icon.html
It works there but I can't get my version to work. Any idea why?
popover isn't part of OpenLayers but contained in Bootstrap: http://getbootstrap.com/javascript/#popovers
Also see the OpenLayers example on overlays: https://openlayers.org/en/latest/examples/overlay.html
With OpenLayers 3, how can I specify a minimum cluster size so that clusters with 5 map markers or less will not get clustered, but will instead display the individual map markers? Is there a way to do this within the cluster layer's ol.layer.Vector object?
let clusterSource = new ol.source.Cluster({
distance: CLUSTER_DISTANCE,
source: features
});
let clusterLayer = new ol.layer.Vector({
source: source,
style: function(feature, resolution) { }
});
You can check in the code how many features are there. If you have too many, you can create a cluster source based on the vector source you already have to add it a to a new vector layer. If not, a vector layer can be created with your existing vector source.
Since there is no method to set the source dynamically to a layer, your vector layer should be created with the desired source. If you want to see how it works with more than 5 features, just uncomment the commented lines.
var features = [
new ol.Feature({
geometry: new ol.geom.Point([0,0])
}),
new ol.Feature({
geometry: new ol.geom.Point([100000,500000])
}),
new ol.Feature({
geometry: new ol.geom.Point([500000,100000])
}),
new ol.Feature({
geometry: new ol.geom.Point([5000000,1000000])
}),
new ol.Feature({
geometry: new ol.geom.Point([1000000,500000])
})
/*,new ol.Feature({
geometry: new ol.geom.Point([1800000,800000])
})*/
],
source = new ol.source.Vector({
features: features
});
var layer;
if (features.length > 5) {
var clusterSource = new ol.source.Cluster({
distance: parseInt(40, 10),
source: source
});
var styleCache = {};
layer = new ol.layer.Vector({
source: clusterSource,
style: function(feature) {
var size = feature.get('features').length;
var style = styleCache[size];
if (!style) {
style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: '#AAA'
}),
fill: new ol.style.Fill({
color: '#DDD'
})
}),
text: new ol.style.Text({
text: size.toString(),
fill: new ol.style.Fill({
color: '#B144FF'
})
})
});
styleCache[size] = style;
}
return style;
}
});
} else {
layer = new ol.layer.Vector({
source: source
});
}
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
layer
],
target: 'clusterMap',
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
<link href="https://openlayers.org/en/v3.20.1/css/ol.css" rel="stylesheet"/>
<script src="https://openlayers.org/en/v3.20.1/build/ol.js"></script>
<div id="clusterMap" class="map"></div>