How to Draw Multi Line string With GeoJSON Object Openlayers - javascript

I am trying to draw linestring by holding the GeoJSON object. But when drawing process starts, the pointer can be selected everywhere on the map. My purpose is the pointer just be selected on the GeoJSON object
Here is some of the code.
var jsonSource = new ol.source.Vector({
url: 'https://raw.githubusercontent.com/Kardelennkayaa/ankr_tdelay/main/KAMAN.json',
format: new ol.format.GeoJSON(),
});
var vector = new ol.layer.Vector({
source: jsonSource,
background: 'white',
});
map.addLayer(vector)
var jsonSource_ank = new ol.source.Vector({
url: 'https://raw.githubusercontent.com/Kardelennkayaa/heroku_app/main/ankara_road.json',
format: new ol.format.GeoJSON(),
});
var vector_ank = new ol.layer.Vector({
source: jsonSource_ank,
background: 'white',
});
map.addLayer(vector_ank)
var draw_lineString = new ol.interaction.Draw({
type : 'LineString',
//source:drawSource_ls
source:jsonSource
})
draw_lineString.on('drawstart', function(evt){
drawSource_ls.clear()
//select.setActive(true);
})
draw_lineString.on('drawend',function(evt){
// alert('point is added')
clickedCoord_lineString = evt.feature.getGeometry().getCoordinates()
$('#ls_adding').modal('show');
console.log('clicked at', evt.feature.getGeometry().getCoordinates())
map.removeInteraction(draw_lineString)
})
function startDrawing_lineString(){
map.addInteraction(draw_lineString)
}
And here is the web interface
The goal is when clicking on the Add LineString, the polyline can be drawn with the relative GeoJSON object. How can I do that? Thanks in advance.

Related

OpenLayers4: How to give icon a bigger click radius

I am trying to make an Icon feature that I can click on easier on mobile phones. I have an icon set up nicely and when using a mouse to click on it there is no issue. However when using my finger or thumb on a mobile phone it is quite difficult to get an accurate click. I am using a ol.geom.Point and giving it an icon style. I tried an ol.geom.Circle but I can't get the icon style to work with it.
Here is an example of my working ol.geom.Point:
for (i in spots) {
var spot = spots[i];
var coords = spot['coords'];
var lat = parseFloat(coords.split(',')[0]);
var lng = parseFloat(coords.split(',')[1]);
var iconFeature = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([lng, lat])),
type: 'spot'
});
iconFeature.setStyle(spotMarker);
features.push(iconFeature);
}
vectorSourceSpots = new ol.source.Vector({
features: features
});
var vectorLayer = new ol.layer.Vector({
source: vectorSourceSpots
});
map.addLayer(vectorLayer);
Here is the spotMarker style:
var spotMarker = new ol.style.Style({
image: new ol.style.Icon(({
src: 'images/spot.png'
}))
});
I've also tried with a ol.geom.Circle but I could not see my icon when I tried this:
for (i in spots) {
var spot = spots[i];
var coords = spot['coords'];
var lat = parseFloat(coords.split(',')[0]);
var lng = parseFloat(coords.split(',')[1]);
var iconFeature = new ol.Feature({
geometry: new ol.geom.Circle(ol.proj.fromLonLat([lng, lat]), 5),
type: 'spot'
});
iconFeature.setStyle(spotMarker);
features.push(iconFeature);
}
vectorSourceSpots = new ol.source.Vector({
features: features
});
var vectorLayer = new ol.layer.Vector({
source: vectorSourceSpots
});
map.addLayer(vectorLayer);
What I want is to have the icon remain the same size, but just to increase the click radius around the icon. Almost like an invisible circle a bit bigger than the icon with the same center.
Is this possible?
You will use forEachFeatureAtPixel to add event on the features, then you can set hitTolerance on its options parameter.
check this api document: forEachFeatureAtPixel
you may need to write:
var addEvent = function(map, evt) {
map.forEachFeatureAtPixel(evt.pixel, function(feature, layer) {
}, {
hitTolerance: 10
});
};
map.on('click', function(evt) {
addEvent(map, evt);
});

Openlayers 3 Coords

I'm newbee of OL. I need just to put some point on the map and ideally make some request for writting info about this point to db, but now i just want to alert(coords) of point. So, i found an example, where i can put some point, line and polygone to the map.
var raster = new ol.layer.Tile({
source: new ol.source.OSM()
});
var map = new ol.Map({
layers: [raster],
target: 'map',
view: new ol.View({
center: [-11000000, 4600000],
zoom: 4
})
});
var features = new ol.Collection();
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: 7,
fill: new ol.style.Fill({
color: '#ffcc33'
})
})
})
});
featureOverlay.setMap(map);
var modify = new ol.interaction.Modify({
features: features,
// the SHIFT key must be pressed to delete vertices, so
// that new vertices can be drawn at the same position
// of existing vertices
deleteCondition: function(event) {
//var feature = event.element;
//var coord = event.feature.getGeometry().getCoordinates();
//coord = ol.proj.transform(coord, 'EPSG:3857', 'EPSG:4326');
// alert(coord);
return ol.events.condition.shiftKeyOnly(event) &&
ol.events.condition.singleClick(event);
}
});
map.addInteraction(modify);
var draw; // global so we can remove it later
var typeSelect = document.getElementById('type');
function addInteraction() {
draw = new ol.interaction.Draw({
features: features,
type: /** #type {ol.geom.GeometryType} */ (typeSelect.value)
/*draw.on('drawend', function (event) {
// get the feature
var feature = event.element;
var coord = event.feature.getGeometry().getCoordinates();
alert(coord);*/
});
map.addInteraction(draw);
}
/**
* Handle change event.
*/
typeSelect.onchange = function() {
map.removeInteraction(draw);
addInteraction();
};
addInteraction();
// Code of adding to DB our features
//
<?php
/* #var $this yii\web\View */
use yii\helpers\Html;
use sibilino\yii2\openlayers\ol;
use sibilino\yii2\openlayers\OpenLayers;
?>
<!DOCTYPE html>
<html>
<head>
<title>Draw and Modify Features</title>
<link rel="stylesheet" href="http://openlayers.org/en/v3.18.2/css/ol.css" type="text/css">
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
<script src="http://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="http://openlayers.org/en/v3.18.2/build/ol.js"></script>
</head>
<body>
<div id="map" class="map"></div>
<form class="form-inline">
<label>Geometry type </label>
<select id="type">
<option value="Point">Point</option>
<option value="LineString">LineString</option>
<option value="Polygon">Polygon</option>
</select>
</form>
<script>
</script>
</body>
</html>
It works normally with all libs, and I can put points, lines and polygones to the map, but I can't get coord of the points, which I put. I tried to create some listener, it's commented in this code, looks like
//var feature = event.element;
//var coord = event.feature.getGeometry().getCoordinates();
//coord = ol.proj.transform(coord, 'EPSG:3857', 'EPSG:4326');
// alert(coord);
But this method as I understood listens mouse moving too, and I'm getting some errors like:
Uncaught TypeError: Cannot read property 'getGeometry' of undefined
If somebody have time to read this long question, what can I do, and how to do right for getting my coords and saving this to DB?
I just needed to redact this code:
function addInteraction() {
draw = new ol.interaction.Draw({
features: features,
type: /** #type {ol.geom.GeometryType} */ (typeSelect.value)
/*draw.on('drawend', function (event) {
// get the feature
var feature = event.element;
var coord = event.feature.getGeometry().getCoordinates();
alert(coord);*/
});
map.addInteraction(draw);
}
To:
function addInteraction() {
draw = new ol.interaction.Draw({
features: features,
type: /** #type {ol.geom.GeometryType} */ (typeSelect.value)
});
// Code of adding to DB our features
draw.on('drawend', function (event) {
var feature = event.element;
var coord = event.feature.getGeometry().getCoordinates();
alert(coord);
var title=document.getElementById('type');
var url = "http://localhost/basic/web/index.php?r=sggis/create&title="+title.value+"&point="+coord;
function lol(){
var xhr = new XMLHttpRequest();
xhr.open("GET", url, false);
xhr.send();
}
lol();
});
And in yii2 Controller i have written an action which just gets title and coords just from the request. It's unsafe, but then I'll redact this one.
At all, every point, line or poly which i put on the map saves their coords to postgresSQL's DataBase.

Failing to load another WFS using the WFS example from the site of OpenLayers 3 as base

I'm starter with OpenLayers3 and I am new on this site so this is my first question and hope I drop it correctly here. What does not work for me is to open a (not tiled?) WFS layer in OpenLayers3. I use as a base a WFS example of the site of open layers (also because it seems to be a relatively simple code). I tried to find a solution in my textbooks OpenLayers3, on the site of open layers, with Google and on this site but without success.
Below the code I made with the example of OpenLayers and again but now for another WFS as I think it should be to open this WFS. What am I doing wrong?
// working example from: http://openlayers.org/en/v3.13.1/examples/vector-wfs.html
var vectorSource = new ol.source.Vector({
format: new ol.format.GeoJSON(),
url: function(extent) {
return 'http://demo.boundlessgeo.com/geoserver/wfs?service=WFS&' +
'version=1.1.0&request=GetFeature&typename=osm:water_areas&' +
'outputFormat=application/json&srsname=EPSG:3857&' +
'bbox=' + extent.join(',') + ',EPSG:3857';
},
strategy: ol.loadingstrategy.tile(ol.tilegrid.createXYZ({
maxZoom: 19
}))
});
var vector1 = new ol.layer.Vector({
source: vectorSource,
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'rgba(0, 255, 255, 1.0)',
width: 2
})
})
});
// The not working code based on the example code above
var vectorSource = new ol.source.Vector({
format: new ol.format.GeoJSON(),
url: function(extent) {
return 'https://geodata.nationaalgeoregister.nl/bestuurlijkegrenzen/wfs?service=WFS&' +
'version=1.1.0&request=GetFeature&typename=bestuurlijkegrenzen:gemeenten&' +
'outputFormat=application/json&srsname=EPSG:28992&' +
'bbox=' + extent.join(',') + ',EPSG:28992';
},
strategy: ol.loadingstrategy.tile(ol.tilegrid.createXYZ({
maxZoom: 19
}))
});
var vector = new ol.layer.Vector({
source: vectorSource,
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'rgba(0, 255, 255, 1.0)',
width: 2
})
})
});
Unless you provide your full code I can only make some guesses.
Your two layers have different projections. I guess you use epsg:3857 for your view projection and so using coordinates from this extent will return 0 features. A first thing to try is to request your layer from geoserver using the projection of your view.
var vectorSource = new ol.source.Vector({
format: new ol.format.GeoJSON(),
url: function(extent) {
return 'https://geodata.nationaalgeoregister.nl/bestuurlijkegrenzen/wfs?service=WFS&' +
'version=1.1.0&request=GetFeature&typename=bestuurlijkegrenzen:gemeenten&' +
'outputFormat=application/json&srsname=EPSG:3857&' +
'bbox=' + extent.join(',') + ',EPSG:3857';
},
strategy: ol.loadingstrategy.tile(ol.tilegrid.createXYZ({
maxZoom: 19
}))
});
This will force geoserver to do the reprojection on the server side.
I would suggest to first try the above so make sure this is your case. Then you have to deside whether you want to do the rerpojection on client or on the server side.

OpenLayers 3: Trying to add image underlay to a vector layer

currently i have a vector map displayed using a KML file as the vector source.
what i want to do is have an image underlay this vector map.
The map is an indoor floormap, the image is the exact same as the vector map only there is more details in it, text written on it etc. What i need is for the map image to underlay the vector map so that the walls of the vector map align perfectly with the walls of the image. This can happen because the KML was created by tracing on top of the images using QGIS.
so far ive been able to have the KML vector map and png image appear on the map, but they are not alligned with each other and are not the same size. This is what i need help with!
here some code for what i currently have:
create the map, no layers yet (maps selected from dropdown boxes)
var map = new ol.Map({
layers: [],
target: 'floormap',
interactions: ol.interaction.defaults({mouseWheelZoom:false}),
view: new ol.View({
center: [0, 0],
zoom: 19,
minZoom: 15,
maxZoom: 30
})
});
add selected map (KML) to map
map.removeLayer(vector);
vector = new ol.layer.Vector({
source: new ol.source.Vector({
url: MAPS_URL + maps[map_id],
format: new ol.format.KML()
})
});
map.addLayer(vector);
setMapExtent(vector);
now i tried to add the image, which works but its not alligned
// this part here i feel may be the problem,
// i just copied and pasted from an example om openlayers.org,
// i dont actually know much about the extent and how to match it to
// the vector map
var extent = [0,0,1024,684];
var projection = new ol.proj.Projection({
code: 'xkcd-image',
units: 'pixels',
extent: extent
});
image = new ol.layer.Image({
source: new ol.source.ImageStatic({
attributions: [
new ol.Attribution({
html: '© xkcd'
})
],
url: MAPS_URL + images[map_id],
projection: projection,
imageExtent: extent
})
});
map.addLayer(image);
the setMapExtent method
function setMapExtent(vectorMap) {
var vectorSource = vectorMap.getSource();
var listenerKey = vectorSource.on('change', function () {
if (vectorSource.getState() === 'ready') {
var extent = vectorSource.getExtent();
map.getView().fitExtent(extent, map.getSize());
vectorSource.unByKey(listenerKey);
}
});
}
at this point i have a vector map with an image sitting way above the map, and the image seems to be smaller too.
Can anyone help me with this issue?
*** Solution! ***
a working solution, although probably not the best way to do it, but it works none the less.
var map = new ol.Map({
layers: [],
target: 'floormap',
interactions: ol.interaction.defaults({mouseWheelZoom:false}),
view: new ol.View({
center: [0, 0],
zoom: 19,
minZoom: 15,
maxZoom: 30
})
});
add new map layer
map.removeLayer(vector);
vector = new ol.layer.Vector({
source: new ol.source.Vector({
url: MAPS_URL + maps[map_id],
format: new ol.format.KML()
})
});
map.addLayer(vector);
setMapExtent(vector);
// call image adding function pass in vector
// to get its extend
addImage(vector);
the addImage function
function addImage(vectorMap) {
var vectorSource = vectorMap.getSource();
// listen for one change on the vector to get the extent of it
// for use in setting the image extent. tried to use on.('load')
// but it didnt work
var listenerKey = vectorSource.once('change', function () {
var extent = vectorSource.getExtent();
var projection = new ol.proj.Projection({
code: 'xkcd-image',
units: 'pixels',
extent: extent
});
image = new ol.layer.Image({
source: new ol.source.ImageStatic({
attributions: [],
url: MAPS_URL + images[map_id],
projection: projection,
imageExtent: extent
})
});
// remove vector layer else they keep stacking up
map.removeLayer(vector);
// add image
map.addLayer(image);
// re-add vector only push so it goes above the image
map.getLayers().push(vector);
});
}
seems to work pretty well! can anyone help me with layer ordering?
Your static image must be georeferenced correctly with the view's projection.
Default view's projection is EPSG:3857 (Spherical Mercator)., the extent of this projection is [-20026376.39, -20048966.10, 20026376.39, 20048966.10]
In your code you specify a projection in pixels for your static layer. You need to use the view's projection, something like this :
// Here the extent of your layer in EPSG:3857 -> [minx, miy, max, mayy]
var extent = [-10000000, -10000000, 10000000, 10000000];
image = new ol.layer.Image({
source: new ol.source.ImageStatic({
attributions: [
new ol.Attribution({
html: '© xkcd'
})
],
url: MAPS_URL + images[map_id],
imageSize: [1024, 684], // Don't forget the image size here
imageExtent: extent
})
});
map.addLayer(image);
Update:
For layer ordering if you want your vector layer on top use push:
http://openlayers.org/en/v3.8.2/apidoc/ol.Collection.html#push
map.getLayers().push(vector)

Openlayers 3 - Issue using a polygon as a background

I am developing a solution that uses Openlayers 3 to display static images of text documents that have been converted from PDFs. Some of my documents are black text on a white background - the page I'm displaying openlayers on is also black, as is the map background - so the document is invisible.
My current solution is to draw a white filled polygon at the same extent as the image being loaded but behind the text - essentially providing a white background for the extent I'm interested in.
The problem is when I pan around, the polygon is constantly redrawing, causing some undesirable effects. See this jsFiddle for an example.
Is there an alternative way of setting the background colour of a layer or is there a setting that will prevent the polygon from flickering.
CSS
body{
background-color:black;
}
HTML
<div id="map" class="map"></div>
Javascript
var imgURL = 'http://i.stack.imgur.com/9C8Xu.png';
var extent = [0,0,488,198];
var projection = new ol.proj.Projection({
units: 'pixels',
extent: extent
});
//A polygon that will represent a white background
var polyFeature = new ol.Feature({
geometry: new ol.geom.Polygon([
[
[0, extent[1]],
[0, extent[3]],
[extent[2], extent[3]],
[extent[2], extent[1]]
]
])
});
//A base layer to hold the polygon feature
var baseLayer = new ol.layer.Image({
source: new ol.source.ImageVector({
source: new ol.source.Vector({
features: [polyFeature]
}),
style: new ol.style.Style({
fill: new ol.style.Fill({color: 'white'})
})
})
});
var docLayer = new ol.layer.Image({
source: new ol.source.ImageStatic({
url: imgURL,
imageExtent: extent
})});
// build the map
var map = new ol.Map({
layers:[baseLayer,docLayer],
target: 'map',
view: new ol.View({
projection: projection,
center: ol.extent.getCenter(extent),
zoom: 2.5
})
});

Categories