I am a novice to OpenLayers, so sorry for an obvious (and perhaps dumb) question, for which I found different approaches for solutions, but none working. Tried this and that, a dozen different suggestions (here, here, here, here, here) but in vain.
Basically, I want to pass the coordinates of a drawn rectangle to another webservice. So, after having drawn the rectangle, it should spit me out the four corners of the bounding box.
What I have so far is the basic OL layers example for drawing a rectangle:
var source = new ol.source.Vector({wrapX: false});
vector = new ol.layer.Vector({
source: source,
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(0, 255, 0, 0.5)'
}),
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 2
}),
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({
color: '#ffcc33'
})
})
})
});
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vector
],
view: new ol.View({
center: ol.proj.fromLonLat([37.41, 8.82]),
zoom: 4
})
});
var draw; // global so we can remove it later
function addInteraction()
{
var value = 'Box';
if (value !== 'None')
{
var geometryFunction, maxPoints;
if (value === 'Square')
{
value = 'Circle';
geometryFunction = ol.interaction.Draw.createRegularPolygon(4);
}
else if (value === 'Box')
{
value = 'LineString';
maxPoints = 2;
geometryFunction = function(coordinates, geometry)
{
if (!geometry)
{
geometry = new ol.geom.Polygon(null);
}
var start = coordinates[0];
var end = coordinates[1];
geometry.setCoordinates([
[start, [start[0], end[1]], end, [end[0], start[1]], start]
]);
return geometry;
};
}
draw = new ol.interaction.Draw({
source: source,
type: /** #type {ol.geom.GeometryType} */ (value),
geometryFunction: geometryFunction,
maxPoints: maxPoints
});
map.addInteraction(draw);
}
}
addInteraction();
Now, what comes next? What is a good way of extracting the bounding box?
Thanks for any hints!
You need to asign a listener to the draw interaction. Like so:
draw.on('drawend',function(e){
alert(e.feature.getGeometry().getExtent());
});
Here is a fiddle
Related
I have a leaflet map using leaflet-realtime to display and update a position, polygon and line from a geoJson source (data is the position and field of view from an airborne camera). I want to change the style of the line and polygon from the default blue. I understand the leaflet-realtime extends L.geojson so I thought the following code should work but I get options.style is not a function. I have been looking at other examples to try and do this but have spent the day frustrated.
var lineStyle = {
color: 'black',
weight: 5,
opacity: 0.5
}
los = L.realtime({
url: 'http://127.0.0.1/geojson/los2.geojson',
crossOrigin: true,
type: 'json'
}, {
interval: 1 * 500,
style: lineStyle
}).addTo(map);
los.on('update', function(){
map.flyTo(
[this._features.los.geometry.coordinates[1][1],
this._features.los.geometry.coordinates[1][0]]
)
});
If anyone can point me in the right direction it would be hugely appreciated.
Thanks
Yes options.style must be a function - look at:
https://leafletjs.com/reference-1.7.1.html#geojson-style
Change your code:
var lineStyle = {
color: 'black',
weight: 5,
opacity: 0.5
}
los = L.realtime({
url: 'http://127.0.0.1/geojson/los2.geojson',
crossOrigin: true,
type: 'json'
}, {
interval: 1 * 500,
style: function() { return lineStyle; }
}).addTo(map);
los.on('update', function(){
map.flyTo(
[this._features.los.geometry.coordinates[1][1],
this._features.los.geometry.coordinates[1][0]]
)
});
I currently have an openlayers map that I am putting a draw overlay on top of. The problem is that when I scale the div container holding the map it doesn't actually scale the drawing layer correctly, so the pointer does not align with the mouse location. If I don't do any scaling it lines up correctly. I have also tried setting the html and body to 100% width in addition to the div tag, but that has not worked either.
mouse aligned
mouse not aligned
here is my map typesscript code:
// create the bing maps layer
var raster = new ol.layer.Tile({
source: new ol.source.BingMaps({
key: 'AioGchlm6KiMF-8ws9hq9PEJKSZzGXj8aZ1OrDt-MlN_NY907-YdiaraNT9sCodZ',
imagerySet: 'AerialWithLabels',
maxZoom: 19
})
});
// generate the actual map
var map = new ol.Map({
layers: [raster],
target: 'map',
view: new ol.View({
center: [-11000000, 4600000],
zoom: 10
})
});
// holds each of the drawings
var features = new ol.Collection();
// allows the user to draw a polygon on the map
var draw = new ol.interaction.Draw({
features: features,
type: 'Polygon'
});
map.addInteraction(draw);
// adds the polygon to the features collection when the drawing is complete
var featureOverlay = new ol.layer.Vector({
source: new ol.source.Vector({features: features}),
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: 4,
fill: new ol.style.Fill({
color: '#ffcc33'
})
})
})
});
featureOverlay.setMap(map);
// allows the user to modify the drawings
var modify = new ol.interaction.Modify({
features: features,
/*
deleteCondition: function(event) {
return ol.events.condition.shiftKeyOnly(event) &&
ol.events.condition.singleClick(event);
}
*/
});
map.addInteraction(modify);
and the html code:
<div #map id="map"></div>
and the css:
#map {
height: 100%;
}
it is also probably worth noting that I am doing this inside an ionic 3 project.
I am very new to OpenLayers and JavaScript, and I have the following problem.
I have an .csv table representing the coordinates of points I want to visualize them on a map using OpenLayers.
I have found the following example on the OpenLayers page,
https://openlayers.org/en/latest/examples/polygon-styles.html
However, I couldn't understand the representation of the coordinates there. More specifically, I didn't know what does the e mean in the coordinate [-5e6, 6e6] for example.
However, I tried to plot a simple square on my map using my coordinates, but it just giving me a point, in the center of the map, as following:
https://jsfiddle.net/api/post/library/pure/#&togetherjs=bD5bfPm7vz
So I don't know what's exactly is wrong, and what should I change? I think it's all in the way the coordinates are written, but not sure though.
And this is my code:
var styles = [
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)'
})
}),
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);
}
})
];
var geojsonObject = {
'type': 'FeatureCollection',
'crs': {
'type': 'name',
'properties': {
'name': 'EPSG:3857'
}
},
'features': [{
'type': 'Feature',
'geometry': {
'type': 'Polygon',
'coordinates': [[[-5e6, 6e6], [-5e6, 8e6], [-3e6, 8e6],
[-3e6, 6e6], [-5e6, 6e6]]]
}
}]
};
var source = new ol.source.Vector({
features: (new ol.format.GeoJSON()).readFeatures(geojsonObject)
});
var layer = new ol.layer.Vector({
source: source,
style: styles
});
var basic = new ol.layer.Tile({
source: new ol.source.OSM()
});
var map = new ol.Map({
layers: [basic, layer],
target: 'map',
view: new ol.View({
center: [0, 3000000],
zoom: 2
})
});
OK, I found the answer.
The following coordinates [-5e6, 6e6] is in X,Y format, and is based on the EPSG:3857 projection. XeY is equal to X * 10 ^ Y. Normally the openlayers use the EPSG:3857 projection, but in order to use the longitude/latitude coordinates format, we have to use the projection: EPSG:4326 projection, and we specify it clearly like: projection: 'EPSG:4326
I'm trying to add a static label to a few CircleMarkers I've created. These markers are added to a LayerGroup and then added to the map. I've read that I need to call .showLabel() after I've added it to the object to the map. But since I am building the LayerGroup first, then adding it to the map I'm unsure of how to do this.
I thought about using L.LayerGroup.eachLayer but I'm unsure which object I would actually call the .showLayers() on. My code is below, any help is appreciated, thanks!
var jsonLayers = new L.LayerGroup();
jsonLayers.addLayer(L.geoJson(mapFeature.features[i], {
style: function (feature) {
return feature.properties && feature.properties.style;
},
onEachFeature: onEachFeature,
pointToLayer: function (feature, latlng) {
var newCircle = L.circleMarker(latlng, {
radius: 5,
fillColor: fColor,
color: "#000",
weight: 1,
opacity: 1,
fillOpacity: 0.8
});
newCircle.bindLabel(feature.properties.name, { noHide: true });
return newCircle;
}
}));
map.addLayer(jsonLayers);
It turns out that static labels are not supported on CircleMarkers. To solve this, I added code to Leaflet.label to allow this. I've also issued a pull request in case someone else would like to do the same thing I am doing.
I have three kml layers in a map: polygons, lines, points.
The map is modified from the mobile-wms-vienna example. I have changed the layers, and changed the "Labels" button to alter the opacity on the polygon layer.
To ensure that all features can be seen I need set z-indexing.
However I would also like to be able to display a pop-up on the polygon layer, which is set as the lowest. I do not want to see popups from lines or points. (Points can have labels, lines do not need labeling). I have read many posts about the problems with select on multiple layers, but could not find a solution to how to make anything selectable when z-indexing is set.
Is there a way to do this? Preferably draw the layers in the order they are added to the map.
Or a label layer that moves with the map and zoom changes? Unfortunately, kml polygon labels are fixed to a point and so might disappear when the map is moved or zoomed in.
The entire map code is given below, as I am not sure if there is something else in my map that is affecting this behaviour.
var map;
var linetyle = new OpenLayers.Style({'strokeWidth': 2, 'strokeColor':"red",});
function init() {
document.documentElement.lang = (navigator.userLanguage || navigator.language).split("-")[0];
var layerPanel = new OpenLayers.Control.Panel({
displayClass: "layerPanel",
autoActivate: true
});
var opButton = new OpenLayers.Control({
type: OpenLayers.Control.TYPE_TOGGLE,
displayClass: "opButton",
eventListeners: {
activate: function() {
if (polygon) {polygon.setOpacity(0.4);}
},
deactivate: function() {
if (polygon) {polygon.setOpacity(0.9);}
}
}
});
layerPanel.addControls([opButton]);
var zoomPanel = new OpenLayers.Control.ZoomPanel();
// Geolocate control for the Locate button - the locationupdated handler
// draws a cross at the location and a circle showing the accuracy radius.
var geolocate = new OpenLayers.Control.Geolocate({
type: OpenLayers.Control.TYPE_TOGGLE,
bind: false,
watch: true,
geolocationOptions: {
enableHighAccuracy: false,
maximumAge: 0,
timeout: 7000
},
eventListeners: {
activate: function() {
map.addLayer(vector);
},
deactivate: function() {
map.removeLayer(vector);
vector.removeAllFeatures();
},
locationupdated: function(e) {
vector.removeAllFeatures();
vector.addFeatures([
new OpenLayers.Feature.Vector(e.point, null, {
graphicName: 'cross',
strokeColor: '#f00',
strokeWidth: 2,
fillOpacity: 0,
pointRadius: 10
}),
new OpenLayers.Feature.Vector(
OpenLayers.Geometry.Polygon.createRegularPolygon(
new OpenLayers.Geometry.Point(e.point.x, e.point.y),
e.position.coords.accuracy / 2, 50, 0
), null, {
fillOpacity: 0.1,
fillColor: '#000',
strokeColor: '#f00',
strokeOpacity: 0.6
}
)
]);
map.zoomToExtent(vector.getDataExtent());
}
}
});
zoomPanel.addControls([geolocate]);
map = new OpenLayers.Map({
div: "map",
theme: null,
projection: new OpenLayers.Projection("EPSG:3857"),
displayProjection: new OpenLayers.Projection("EPSG:4326"),
layers: [new OpenLayers.Layer.Google( "Google Satellite", {type: google.maps.MapTypeId.SATELLITE, numZoomLevels: 22})],
center: new OpenLayers.LonLat(149.1, -35.3).transform('EPSG:4326', 'EPSG:3857'),
zoom: 10,
units: "m",
maxResolution: 38.21851413574219,
controls: [
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.Attribution(),
zoomPanel,
layerPanel
],
});
layerPanel.activateControl(opButton);
// Vector layer for the location cross and circle
var vector = new OpenLayers.Layer.Vector("Vector Layer");
var point = new OpenLayers.Layer.Vector("points", {
// rendererOptions: {zIndexing: 'true'},
projection: map.displayProjection,
strategies: [new OpenLayers.Strategy.BBOX()],
protocol: new OpenLayers.Protocol.HTTP({
url: "kml/point.kml",
format: new OpenLayers.Format.KML({
extractStyles: true,
extractAttributes: true
}) }) });
var line = new OpenLayers.Layer.Vector("line", {
// rendererOptions: {zIndexing: 'true'},
projection: map.displayProjection,
strategies: [new OpenLayers.Strategy.BBOX({resFactor: 1})],
styleMap: linetyle,
protocol: new OpenLayers.Protocol.HTTP({
url: "kml/line.kml",
format: new OpenLayers.Format.KML({ extractStyles: false,
extractAttributes: true
}) }) });
var polygon = new OpenLayers.Layer.Vector("Geology", {
// rendererOptions: {zIndexing: 'true'},
projection: map.displayProjection,
strategies: [new OpenLayers.Strategy.BBOX({resFactor: 1})],
protocol: new OpenLayers.Protocol.HTTP({
url: "kml/polygon.kml",
format: new OpenLayers.Format.KML({extractStyles: true,extractAttributes: true})
}) });
map.addLayers([point, line, polygon]);
polygon.setOpacity(0.5);
// point.setZIndex(1400);
// line.setZIndex(1300);
// polygon.setZIndex(1200);
// Select Features/Popup
select = new OpenLayers.Control.SelectFeature (polygon, line, point);
polygon.events.on({
"featureselected": onFeatureSelect,
"featureunselected": onFeatureUnselect
}),
line.events.on({
"featureselected": onFeatureSelect,
"featureunselected": onFeatureUnselect
}),
point.events.on({
"featureselected": onFeatureSelect,
"featureunselected": onFeatureUnselect
}),
map.addControl(select);
select.activate();
function onPopupClose(evt) {
select.unselectAll();
}
function onFeatureSelect(event) {
var feature = event.feature;
// Since KML is user-generated, do naive protection against
// Javascript.
var content = "<h2>"+feature.attributes.name + "</h2>" + feature.attributes.description;
if (content.search("<script") != -1) {
content = "Content contained Javascript! Escaped content below.<br>" + content.replace(/</g, "<");
}
popup = new OpenLayers.Popup.FramedCloud("chicken",
feature.geometry.getBounds().getCenterLonLat(),
new OpenLayers.Size(100,100),
content,
null, false, onPopupClose);
feature.popup = popup;
map.addPopup(popup);
}
function onFeatureUnselect(event) {
var feature = event.feature;
if(feature.popup) {
map.removePopup(feature.popup);
feature.popup.destroy();
delete feature.popup;
}
};
};
The map can be seen at http://quartzspatial.net/act/map_v2.html
The closest answer that may solve my problem is here, but I could not understand how to use the solutions, and after many attempts at putting code in different places, I gave up.
I have just been looking at similar problem earlier. You probably figured this out yourself by now but I would like to share my jsFiddle in which I use event listener on the map object instead of a select control.
You cannot use an OpenLayers select control with layers index. The activation event will always put the layers on top and setting the z index on the layers will disable the select control. I also wasn't able to make the solution with disabling the moveontop in the activate event work (in jsFiddle).
Please have a look at the event listener solution:
var map = new OpenLayers.Map({
div: "map",
projection: new OpenLayers.Projection("EPSG:3857"),
displayProjection: new OpenLayers.Projection("EPSG:4326"),
layers: [
new OpenLayers.Layer.OSM()],
controls: [
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.ArgParser() ],
eventListeners: {
featureover: function(e) { if (e.feature.layer != vectors2) {
e.feature.renderIntent = "temporary";
e.feature.layer.drawFeature(e.feature); }
},
featureout: function(e) { if (e.feature.layer != vectors2) {
e.feature.renderIntent = "default";
e.feature.layer.drawFeature(e.feature); }
},
featureclick: function(e) { if (e.feature.layer != vectors2) {
e.feature.renderIntent = "select";
e.feature.layer.drawFeature(e.feature); }
}
}
});