Draw a polygon with Maptiler and OpenLayers - javascript

I want to draw a polygon on a map (MapTiler) using Open Layers.
When I only draw the map and the circle (parts 1 and 2) it looks okay. But if I add part 3 (the polygon) I only see the map. Neither the circle or the polygon are drawn on the map. I guess there is something wrong in the definition of the polygon, but I can't figure it out.
Part 3 updated in accordance with comments posted
/***********************************************************
Part 1: initializing the map
********************************************************* */
var styleJson = 'https://api.maptiler.com/maps/openstreetmap/style.json?key=MyPrivateKey';
var map = new ol.Map({
target: 'map',
view: new ol.View({
constrainResolution: true,
center: ol.proj.fromLonLat([5.8, 51.34]),
zoom: 14
})
});
olms.apply(map, styleJson);
/***********************************************************
Part 2: Draw a circle
********************************************************* */
var centerLongitudeLatitude = ol.proj.fromLonLat([5.8, 51.34]);
var viewProjection = map.getView().getProjection();
var pointResolution = ol.proj.getPointResolution(viewProjection, 1, centerLongitudeLatitude);
var radius = 20;
var Circle = new ol.layer.Vector({
source: new ol.source.Vector({
features: [new ol.Feature(new ol.geom.Circle(centerLongitudeLatitude, radius))]
}),
style: [
new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'red',
width: 2
}),
fill: new ol.style.Fill({
color: 'red'
})
})
],
zIndex: 6,
});
map.addLayer(Circle);
/***********************************************************
UPDATE
- the map is displayed, and
- the circle is drawn,
- but the polygon is still not showing.
Part 3: Drawing a polygon
***********************************************************/
var Line = new ol.layer.Vector({
source: new ol.source.Vector({
features: [new ol.Feature(new ol.geom.Polygon([
[
[5.81, 51.33],
[6.93, 52.44],
[6.93, 52.33],
[5.81, 51.33]
]
])).transform('EPSG:4326', 'EPSG:3857')]
}),
style: [
new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'black',
width: 20
}),
fill: new ol.style.Fill({
color: 'black'
})
})
],
zIndex: 6,
});
map.addLayer(Line);

Related

Openlayers 6: Filter point vector layer by properties before point clustering

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;
}
}
});

Specifying a minimum cluster size with Open Layers Clustering

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>

OpenLayers 3: Show vector labels on hover

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?
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>

OpenLayers 3 - Z-index of features on highlights

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;
}
}
});

Openlayers 3 interaction.draw()

I am trying to create a user interactive circle using the example code from the openlayers example website:
var draw = new ol.interaction.Draw({
features: featureOverlay.getFeatures(),
type: 'Circle'
});
map.addInteraction(draw);
I always get a TypeError when I set, type: Circle, but when I set the type to Point, LineString, or Polygon it works just fine. I looked through the openlayers 3 API documentation and Circle is a valid geometric type. Does anyone here have any information of why I get the type error?
Circle was added to one of the latest version of ol3 (3.4)
Now the latest version is 3.5
I made an example of adding Circle:
js
https://cdnjs.cloudflare.com/ajax/libs/ol3/3.5.0/ol.js
css
https://cdnjs.cloudflare.com/ajax/libs/ol3/3.5.0/ol.min.css
Draw circle
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'osm'})
})
],
view: new ol.View({
center: ol.proj.transform(
[-110, 45], 'EPSG:4326', 'EPSG:3857'),
zoom: 3
})
});
var featureOverlay = new ol.FeatureOverlay({
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.2)'
}),
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 2
}),
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({
color: '#ffcc33'
})
})
})
});
featureOverlay.setMap(map);
var draw = new ol.interaction.Draw({
features: featureOverlay.getFeatures(),
type: 'Circle'
});
map.addInteraction(draw);

Categories

Resources