I am currently working on a openlayers 3 project and for better visulaizing i need to show both. The Polygon shape(attribute based color) which works great and an icon on the polygon position. I know that the polygon contains multiple coordinates and so its not so easy to define a position for the icon. Now i have some kind of workaround that creates an seperate overlay with the interior Points of the polygon to mark the position of the icons. To make the project more simple i want to combine these two styling. Does anyone know if its possible?
Kind Regards
I presumes that you use a ol.source.serversource for your data.
The trick is to test all your features for being a polygon. If it is, you create a point feature you add to your source.
First create the source and the layer:
var avlVectorSource = new ol.source.ServerVector({
format: new ol.format.GeoJSON(),
loader: function(extent, resolution, projection) {
myLoader(resolution);
}
});
var myLayer = new ol.layer.Vector({
source: myVectorSource,
style: myStyleFunction
});
The layer has a style function to set the right icon.
The main thing is the loader:
var myLoader = function(resolution){
$.ajax({
url: "http://myJsonSource.com",
timeout: 1000,
success: function(response) {
var layerJSONString = $.parseJSON(response);
var newFeatures = [];
j= 0;
var size=layerJSONString.features.length;
for (i = 0; i < size; i++){
var feat = layerJSONString.features[i];
var geom = feat.geometry;
var type = geom.type;
if(type == "Polygon")
{
var poly = new ol.geom.Polygon(geom.coordinates);
var extent = poly.getExtent();
var coord = [];
coord[0] = (extent[2]-extent[0])/2 + extent[0];
coord[1] = (extent[3]-extent[1])/2 + extent[1];
var point = new ol.geom.Point(coord);
newFeatures[j++] = new ol.Feature({
geometry : point,
StyleName : feat.properties.StyleName
});
}
}
avlVectorSource.addFeatures(myVectorSource.readFeatures(response));
avlVectorSource.addFeatures(newFeatures);
},
error: myLoadError
});
}
};
The documentation says that ol.geom.Polygon has a method called getInteriorPoint(). It has but I can get it to work. So I calculate the center point of the extent of the polygon.
I use "StyleName" to set the right icon in my style function.
Related
I have a layer with markers and one layer with polylines. The markers are at the end of the polylines. I like to drag any marker synchronous with the end (overapping) of the polyline.
var features = new ol.Collection();
var featureOverlay = new ol.layer.Vector({source: new ol.source.Vector({features: features}),style:styles});
featureOverlay.setMap(map);
var markers = new ol.Collection();
var markerOverlay = new ol.layer.Vector({source: new ol.source.Vector({features: markers}),style:styles});
markerOverlay.setMap(map);
var modify = new ol.interaction.Modify({features: features});
map.addInteraction(modify);
var modifyn = new ol.interaction.Modify({features: markers});
map.addInteraction(modifyn);
It's not working synchronous. I have to drag the end of the polyline and the marker separate.
How can I drag both at the same time?
Thanks for helping!
Andreas.
I got it!
I collect all features at the mouse position in realtime and save them in a collection. This collection is the feature in modify.
Cheers!
var allFeaturesAtPixel = new ol.Collection();
var modify = new ol.interaction.Modify({features: allFeaturesAtPixel});
map.addInteraction(modify);
map.on('pointermove', function (evt)
{
allFeaturesAtPixel.clear();
map.forEachFeatureAtPixel(evt.pixel, function (feature) {allFeaturesAtPixel.push(feature);});
});
I have to load some Features in a Vector layer and have a style function.
var features = new ol.format.GeoJSON().readFeatures( geojsonStr, {
featureProjection: 'EPSG:3857'
});
var vectorSource = new ol.source.Vector({
features: features,
});
/*
var clusterSource = new ol.source.Cluster({
distance: 15,
source: vectorSource
});
*/
var customStyleFunction = function( feature, resolution ) {
....
}
var vectorLayer = new ol.layer.Vector({
//source: clusterSource,
source: vectorSource,
style : customStyleFunction
});
map.addLayer( vectorLayer );
I don't know what kind of geometry I will get in geojsonStr. The problem is: When my collection is of type "Point" I can cluster it, but with any other types I can't see the Layer... How can I cluster Points and ignore Polygons and Lines? or let OL3 be clever enough to decide?
EDIT: I've read https://github.com/openlayers/openlayers/pull/4917
I would recommend you to create 2 different layers: One for clustering and a another one for a common vector layer.
To solve your problem, you can loop through the features and check the geometry type of each, and add it to an already existing source with the addFeature method:
for (var i = 0; i < geojsonFeatures.length; i++) {
if (geojsonFeatures[i].getGeometry().getType() === 'Point') {
clusterSource.addFeature(geojsonFeatures[i]);
} else {
vectorSource.addFeature(geojsonFeatures[i]);
}
}
I have created a jsfiddle which gets a couple of features from a GeoJSON object and add them to different sources depending on the geometry type. If you want to see more points in the cluster souce to make sure that it is working properly, you can use the commented lines as well.
I am creating an application which utilises a map created and managed by the OpenLayers 3 library. I want to be able to switch which layer is visible using the zoom level (i.e. zoom out to get an overview of countries, zoom in to get an overview of cities). There are three categories of layers (3 different zoom levels), and within each category there are 3 colours which the pins I am using could be (which are all separate layers as well) so in total there are 9 layers.
What I want is to develop the ability to filter which layers are displayed, which means showing/hiding the existing layers depending on which zoom level we are at.
There is some code to demonstrate how the map is generated and how one type of layer is generated but if there is more detail required please let me know. I don't believe there will be an issue with this, however.
function setUpMap(vectorLayers, $scope){
var view = new ol.View({
center: ol.proj.fromLonLat([2.808981, 46.609599]),
zoom: 4
});
map = new ol.Map({
target: 'map',
layers: vectorLayers,
overlays: [overlay],
view: view
});
view.on("change:resolution", function(e){
var oldValue = e.oldValue;
var newValue = e.target.get(e.key);
if (newValue > 35000){
if (oldValue < 35000)
//This is where I will show group 1
} else if (newValue > 10000){
if (oldValue < 10000 || oldValue > 35000)
//This is where I will show group 2
} else {
if (oldValue > 10000)
//This is where I will show group 3
}
});
addClickEventsToMapItems($scope);
}
I tried something like this and got no success:
function showLayer(whichLayer){
vectorLayers[1].setVisibility(false);
vectorLayers[2].setVisibility(false);
vectorLayers[3].setVisibility(false);
vectorLayers[whichLayer].setVisibility(true);
}
I am open to suggestions. Please let me know! :)
You can listen to the resolution:change event on your ol.Map instance:
map.getView().on('change:resolution', function (e) {
if (map.getView().getZoom() > 0) {
vector.setVisible(true);
}
if (map.getView().getZoom() > 1) {
vector.setVisible(false);
}
});
Example on Plunker: http://plnkr.co/edit/szSCMh6raZfHi9s6vzQX?p=preview
It's also worth to take a look at the minResolution and maxResolution options of ol.layer which can switch automaticly for you. But it works by using the view's resolution, not the zoomfactor:
http://openlayers.org/en/v3.2.1/examples/min-max-resolution.html
why dont you use minResolution/maxResolution parameters during vector layer initialasation, check the api here
If you dont know the resolution but you know only the scale, use the following function to get the resolution out of the scale
function getResolutionFromScale(scale){
var dpi = 25.4 / 0.28;
var units = map.getView().getProjection().getUnits();
var mpu = ol.proj.METERS_PER_UNIT[units];
var res = scale / (mpu * 39.37 * dpi);
return res;
}
I use a geojson file to build the layer added to a map. What I want is to customize style of the layer's polygons in order to have hatched polygons such as we can do that with mapserver symbols. Is it possible to do this with ol3? I tried to create an image and use it but it only works for point geometry. Thank you for your help.
Regards.
Fill patterns for polygons are not (yet) supported in OpenLayers 3, see also https://github.com/openlayers/ol3/issues/2208
It is possible by now. The ol.style.Style object accepts a CanvasRenderingContext2D instance, where you can apply an image pattern to your polygons.
Example Code Snippet
var geojsonObject = 'someGeoJSON'
var source = new ol.source.Vector({
features: (new ol.format.GeoJSON()).readFeatures(geojsonObject)
});
var layer = new ol.layer.Vector({
source: source
});
var cnv = document.createElement('canvas');
var ctx = cnv.getContext('2d');
var img = new Image();
img.src = 'https://mdn.mozillademos.org/files/222/Canvas_createpattern.png';
img.onload = function() {
var pattern = ctx.createPattern(img, 'repeat');
layer.setStyle(new ol.style.Style({
fill: new ol.style.Fill({
color: pattern
})
}));
};
A full example can be seen here: jsfiddle
I am trying to draw a line on top of another line using open layer. The idea is draw a second line top of the predefined line path.
How can we draw a line with starting coordinate and distance on top of the predefined line path?
You can do this by returning a 2nd style from your layer's style function, which has a custom geometry derived from the original one:
var lineStyle = new ol.style.Style(...); // your existing style
var secondLineStyle = new ol.style.Style({
... // styles for the 2nd line
geometry: function(feature) {
var geometry = feature.getGeometry().clone();
... // modify the geometry, e.g. using forEachSegment and getCoordinateAtM
return geometry;
}
});
var layer = new ol.layer.Vector({
style: function(feature, resolution) {
return [
lineStyle,
secondLineStyle
];
}
});