Openlayers 3 : How to change Geojson Icon src so it won't override other geojson types? - openlayers-3

I'm able to change src of an icon when loading Point/MultiPoint Geojson, in this way:
that.geojsonLayers[index] = new that.openlayers.ol.layer.Vector({
source: new that.openlayers.ol.source.Vector({
format: new that.openlayers.ol.format.GeoJSON(),
url: url
}),
style: new that.openlayers.ol.style.Style({
image: new that.openlayers.ol.style.Icon({
src: 'http://mapmip.webiks.com/assets/Markers/marker-icon-blue.png'
})
})
but then I can't load other types of Geojson - Polygons are not being loaded at all, and Geometry Collection (which composed from icon and lines) is load only the icon.
What is the way to change the icon src so it won't override the other geojson type ?

You may use a style function to verify the geometry type you need to style. Setting an icon for styling a polygon is not correct.
Check this
1.Declare your style
var myMultiStyle = {
//here replace with your icon style
'Point': new ol.style.Style({
image: new ol.style.Circle({
fill: new ol.style.Fill({
color: 'rgba(255,255,0,0.4)'
}),
radius: 5,
stroke: new ol.style.Stroke({
color: '#ff0',
width: 1
})
})
}),
'LineString': new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#f00',
width: 3
})
}),
'Polygon': new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(0,255,255,0.5)'
}),
stroke: new ol.style.Stroke({
color: '#0ff',
width: 1
})
})
};
Create a style function
function myStyleFunction(feature,resolution){
return myMultiStyle[feature.getGeometry().getType()];
}
Asign the style function to your vector source
that.geojsonLayers[index] = new that.openlayers.ol.layer.Vector({
source: new that.openlayers.ol.source.Vector({
format: new that.openlayers.ol.format.GeoJSON(),
url: url
}),
style: myStyleFunction
})
Check this official example to see the result.

Related

OpenLayers 3 select style

In OL2 I was able to specify a "select" style in the style definition. In OL3 this doesn't seem to exist. If I understand it correctly, I can set a style for the select interaction. However, this likely won't work in my case since every layer has a unique "selected" style. Am I mistaken in my assessment of the capability? Is there another/optimal way to do this in OL3?
Let's assume that you have a style parameter stored in each ol.Feature, you can add a ol.style.StyleFunction to your ol.interaction.Select and return a style based on this parameter. Like so:
var styles = {
'route': new ol.style.Style({
stroke: new ol.style.Stroke({
width: 6,
color: [237, 212, 0, 0.8]
})
}),
'icon': new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 1],
src: 'pin.png'
})
}),
'geoMarker': new ol.style.Style({
image: new ol.style.Circle({
radius: 7,
snapToPixel: false,
fill: new ol.style.Fill({color: 'black'}),
stroke: new ol.style.Stroke({
color: 'white',
width: 2
})
})
})
};
var select = new ol.interaction.Select({
style: function(feature, resolution) {
return [styles[feature.get('style_parameter')]];
}
});
And your feature would be like:
var geoMarker = new ol.Feature({
style_parameter: 'geoMarker',
geometry: new ol.geom.Point([0,0])
});
I know this a very old thread, but since I haven't been able to find a clear solution to this particular problem yet, I still deem it fit to post mine. Not sure how it holds up with a large number of layers and features, but this is the most elegant and concise solution I could come up with.
BTW: I'm using the latest version of OpenLayers, which at the moment is 6.3.1.
var map = new ol.Map({
...
layers: [
new ol.layer.Vector({
...
// Default style for layer1
style: default1,
// Hover style for layer1 (custom property)
hoverStyle: hover1,
// Selected style for layer1 (custom property)
selectedStyle: selected1
}),
new ol.layer.Vector({
...
// Default style for layer2
style: default2,
// Hover style for layer2 (custom property)
hoverStyle: hover2,
// Selected style for layer2 (custom property)
selectedStyle: selected2
})
],
...
});
var hoverInteraction = new ol.interaction.Select({
condition: ol.events.condition.pointerMove,
style: function(feature) {
var layer = hoverInteraction.getLayer(feature);
return layer.values_.hoverStyle;
}
});
map.addInteraction(hoverInteraction);
var selectInteraction = new ol.interaction.Select({
condition: ol.events.condition.click,
style: function(feature) {
var layer = selectInteraction.getLayer(feature);
return layer.values_.selectedStyle;
}
});

GeoJSON data not displayed on a vector layer

I'm trying to display a vector layer to show a set of geojson features.
When I try and add the layer though I get an error in the ol.js library "k.xd is not a function"
var geoData = {"type":"FeatureCollection",
"features":
[
{"type":"Feature","properties":{"Name":"","Description":""},"geometry":{"type":"Point","coordinates":[0.0,0.0]}},
{"type":"Feature","properties":{"Name":"1","Description":""},"geometry":{"type":"Point","coordinates":[11.50728,3.87471,0.0]}},
]
};
// vector layer
var vector = new ol.layer.Vector({
source: new ol.source.Vector({
features: (new ol.format.GeoJSON()).readFeatures(geoData)
}),
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'red',
width: 2
}),
fill: new ol.style.Fill({
color: 'rgba(255,0,0,0.2)'
})
})
});
I've hacked together an example here http://jsfiddle.net/dxt95yt6/1/ that shows it not working but I can't figure out where this differs from the original tutorials.
Given style object is not correct for points and therefore features just don't show up. Try:
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 8,
stroke: new ol.style.Stroke({
color: 'red',
width: 2
}),
fill: new ol.style.Fill({
color: 'rgba(255,0,0,0.2)'
})
})
})
Please note, in original code, there's another problem, too. Coordinates have to be transformed to EPSG:3857:
features: (new ol.format.GeoJSON()).readFeatures(
geoData,
{featureProjection: ol.proj.get('EPSG:3857')}
)
http://jsfiddle.net/zqx6644q/8/
Its always helpful to validate your geojson before using it. I can recommend geojsonlint which has alos an api to make sure your using a correct geojson.

OpenLayers3 - Style each Feature individually

I am adding features to a map by reading their WKT-String:
var feature = wkt.readFeature(entity.WellKnownText);
feature.bxObject = entity;
src.addFeature(feature);
Each feature has a bxObject-Property, and this Property contains the "radius"-Property.
I style the layer, to which the features are added like so:
var layer = new ol.layer.Vector({
source: src,
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 6,
stroke: new ol.style.Stroke({
color: 'blue',
width: 1
}),
fill: new ol.style.Fill({ color: [0, 0, 255, 0.1] })
})
})
});
I want the radius-Property of the style to be dynamic. What I did and works as a workaround is the following:
var layer = new ol.layer.Vector({
source: src,
style: function (feature, resolution) {
return [
new ol.style.Style({
image: new ol.style.Circle({
radius: feature.bxObject.radius || 6,
stroke: new ol.style.Stroke({
color: 'blue',
width: 1
}),
fill: new ol.style.Fill({ color: [0, 0, 255, 0.1] })
})
})
];
}
});
But this creates a new style for each feature... I potentially draw 100s of features and I even have the subjective opinion, that it slows everything down. Is this really the way it is done?
I found this stackoverflow post. But I had no luck trying to interpolate with "${...}". I guess this is an openLayers 2 feature:
var layer = new ol.layer.Vector({
source: src,
style: new ol.style.Style({
image: new ol.style.Circle({
radius: "${bxObject.radius}",
stroke: new ol.style.Stroke({
color: 'blue',
width: 1
}),
fill: new ol.style.Fill({ color: [0, 0, 255, 0.1] })
})
})
});
Yes this is really the way, but you should keep a style cache and re-use when possible. See for instance: http://openlayers.org/en/v3.10.1/examples/kml-earthquakes.html

Resizing OL3 features programmatically

I have map with user drawn features. After the user custom enters a map scale, I need to be able to resize all the existing map features based on this scale.
What is the way to do this in OL 3? I've seen that in OL 2, there is a geometry.resize function.
Thanks.
You can accomplish this using a StyleFunction.
Look at the following example: http://openlayers.org/en/v3.4.0/examples/vector-layer.html
If you zoom the map, you'll see the labels appear at a certain resolution. This is controlled inside the style function. Here's a snippet:
var featureOverlay = new ol.FeatureOverlay({
map: map,
style: function(feature, resolution) {
// === SEE THIS NEXT LINE ===
var text = resolution < 5000 ? feature.get('name') : '';
if (!highlightStyleCache[text]) {
highlightStyleCache[text] = [new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#f00',
width: 1
}),
fill: new ol.style.Fill({
color: 'rgba(255,0,0,0.1)'
}),
text: new ol.style.Text({
font: '12px Calibri,sans-serif',
text: text,
fill: new ol.style.Fill({
color: '#000'
}),
stroke: new ol.style.Stroke({
color: '#f00',
width: 3
})
})
})];
}
return highlightStyleCache[text];
}
});
So you could define the size you want the features to have for any resolution range. Note that the style property also applies to a ol.layer.Vector layer.
you can use API: map.updateSize().
Reference: http://openlayers.org/en/latest/apidoc/ol.Map.html#updateSize

How to indicate polygon vertices with small circles using OpenLayers?

I am using OpenLayers 3 and have more or less implemented everything in my requirements list, except one thing: I am asked to somehow make the polygon rendering indicate the polygon vertices with small circles.
In plain words, the desired polygon outline is not just a line - it is a line "adorned" with small circles in all the places where there is a vertex.
How can I do that in OL3? I searched in the ol.style.Style docs (that is, the style I pass via setStyle to the ol.layer.Vector containing my polygons), but didn't find anything relevant.
For reference, there is now an example showing how to display the vertices of a polygon with a custom style geometry:
http://openlayers.org/en/master/examples/polygon-styles.html
var styles = [
// style for the polygon
new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'blue',
width: 3
}),
fill: new ol.style.Fill({
color: 'rgba(0, 0, 255, 0.1)'
})
}),
// style for the vertices
new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: 'orange'
})
}),
geometry: function(feature) {
// return the coordinates of the first ring of the polygon
var coordinates = feature.getGeometry().getCoordinates()[0];
return new ol.geom.MultiPoint(coordinates);
}
})
];
The kind OL3 devs have provided the answer on the GitHub issue list. You basically use a style's geometry function, that transforms the geometry before projecting it - and in that function, you add your vertices to a MultiPoint geometry. #tsauerwein went as far as creating a working fiddle - many thanks to him for his work.
var styleFunction = function() {
var image = new ol.style.Circle({
radius: 5,
fill: null,
stroke: new ol.style.Stroke({color: 'orange', width: 2})
});
return [
new ol.style.Style({
image: image,
geometry: function(feature) {
var coordinates = feature.getGeometry().getCoordinates()[0];
return new ol.geom.MultiPoint(coordinates);
}
}),
new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'blue',
width: 3
}),
fill: new ol.style.Fill({
color: 'rgba(0, 0, 255, 0.1)'
})
})
];
};

Resources