Open Layers 5.3.0 project, problem with Point customization - openlayers-5

I'm learning openstreetmaps and openlayers. I started with application approach (Parcel + openlayers). Most of examples you find here, that could possibly help me are used with older code, which as I understand does not support all features such as Clusters and other stuff. I tried them and was not able to make it work with new environment (of cause it was not just copy-past). My question is relatively simple, I want to customize Features with [Points][1], docs say I can set their style by [setStyle][2] they also have example where it actually works. I used that example to start but whatever style I describe in there I see no new point on a map, and there are none any errors in Parsel or in browser console. If I do not use setStyle I see my point on a map. I tried different ways to set a style but none of them actually worked for me.
I do it like that, first I set style:
var iconStyle = new Style({
fill: 'red'
});
After that I add point to features array like that
features.push( new Feature({
geometry: new Point(coordinates),
address: 'Адрес точки 2',
ordererName: 'Имя человека 2',
})
);
and afterwards I set a style for a point:
features[1].setStyle(iconStyle);
and put all of that into map:
var source = new VectorSource({
features: features
});
var vectorLayer = new VectorLayer({
source: source
});
var raster = new TileLayer({
source: new OSM()
});
//EPSG:3857 - web
//EPSG:4326 - GPS
var map = new Map({
layers: [
raster,
//source,
//clusters,
vectorLayer
],
target: 'map',
view: new View({
center: transform(map_center, 'EPSG:4326', 'EPSG:3857'),
zoom: 13
})
});
So my question is how to set a style for a point and actually see on a map? If you also capable to suggest how to add such a custom Point on click on a map after you created a map with layers and points that is highly appreciated. Thanks in advance.

Your style setup isn't complete, to display a point your need to style it as an image, for example a red filled circle
var iconStyle = new Style({
image: new CircleStyle({
radius: 10,
fill: new Fill({
color: 'red'
})
})
});
If adding a feature after creating the map it might look like this:
map.on('click', function(event) {
var feature = new Feature({
geometry: new Point(event.coordinate)
...
...
});
feature.setStyle(...);
source.addFeature(feature);
});

Related

Error with Mapbox GL integration when adding markers: "Cannot read property 'coordinates' of undefined"

I've been working on creating a dynamically updated Mapbox GL integration inside Webflow's CMS. I've succeeded in creating an array of features that can be read by Mapbox's API, but these features won't show on the map because the coordinates are not being read by the function that creates the map markers.
I receive the following error Cannot read property 'coordinates' of undefined at map-test-page:139 which is where a longitude and latitude is assigned to the current marker via this line: .setLngLat(marker.geometry.coordinates)
Partial solution was found here, but the code I've integrated into my site doesn't have featuresIn or featuresAt functions which seem to be the only way to include a includeGeometry: true parameter.
I'm curious if I need to rethink how I've created markers and do something with a function like map.on('click', ...) reference here.
Here is a minimal version that reproduces my issue.
If you're familiar with the Webflow interface you can view a read-only version of the site.
Any help would be greatly appreciated!
Here is the Mapbox script I'm using on the page:
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/strawpari/ckp2nu3dw6cwu17nt4kqwf1vv',
center: [-13.723969, 48.360542],
zoom: 2,
pitch: 0,
bearing: 0,
antialias: true,
interactive: true
});
var geojson = {
type: 'FeatureCollection',
features: farmerArray,
};
// add markers to map
geojson.features.forEach(function(marker) {
// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'marker';
// make a marker for each feature and add to the map
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.setPopup(new mapboxgl.Popup({ offset: 25 }) // add popups
.setHTML('<img src=\'' + marker.properties.image + '\' width=\'50\' height=\'50\' border-radius=\'50%\'>' + '<h3>' + marker.properties.title + '</h3><p>' + marker.properties.description + '</p>'))
.addTo(map);
});
And here is the code embedded in each CMS item that adds a farmer's information to the farmerArray which is being read by Mapbox. Text in double-quotations "" is a placeholder for the dynamic information populated by the CMS.
var farmerArrayItem =
JSON.stringify({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: ["longitude", "latitude"]
},
properties: {
title: "name",
description: "text",
image: "imagepath"
}
});
farmerArray.push(farmerArrayItem);
It doesn't appear that you have tried using the Developer Tools to debug your code. That's definitely a skill you should pick up.
With the dev tools, you will quickly see that the value of marker at the critical point is a string:
So you just need to use JSON.parse:
geojson.features.forEach(function(markerString) {
const marker = JSON.parse(markerString);
// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'marker';
// make a marker for each feature and add to the map
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)

Open Layers: how to do coordinate system transformation on vector-source

I am trying to include a map in my application. I load data from a postgis database, where it is stored as wgs84. The data is loaded as geojson and displayed by open layers.
The problem is that the data is currently being projected somewhere in the ocean, I therefore suspect the data needs to be translated into a different coordinate system.
This is the code to create the map object:
var map = new ol.Map({
projection: 'EPSG:4326',
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM(),
})
],
view: new ol.View({
center: ol.proj.fromLonLat([5, 52]),
zoom: 4
})
});
And this is the code I use to load the data:
function addObjectsToMap()
{
var vectorSource = new ol.source.Vector({
features: new ol.format.GeoJSON().readFeatures( <?php print_r($object->getLocationsAsGeoJson()); ?> )
});
var vectorLayer = new ol.layer.Vector(
{
source: vectorSource
});
map.addLayer(vectorLayer);
}
I have already tried setting the coordinate system of the map to epsg:900913,
I tried adding this in the vectorLayer:
preFeatureInsert: function(feature)
{
feature.geometry.transform(new ol.proj.Projection("EPSG:4326"),new ol.proj.Projection("EPSG:900913"));
},
I tried adding: .transform('EPSG:4326','EPSG:900913') to the dataimport (where the vector source is created)
And I tried looping over the the data in my vectorsource like this:
vectorSource.getFeatures()[i].setGeometry(vectorSource.getFeatures()[i].getGeometry().transform(new ol.proj.Projection("EPSG:4326"),new ol.proj.Projection("EPSG:900913")));
I would really appreciate it if someone could point me in the right direction. Surely this is something common and should be very easy to deal with. But I cannot find anything about it in the documentation or examples of open layers.
The features can be transformed to the view projection using dataProjection and featureProjectiion options when reading the features
features: new ol.format.GeoJSON().readFeatures( <?php print_r($object->getLocationsAsGeoJson()); ?> , {
dataProjection: 'EPSG:4326',
featureProjection: map.getView().getProjection()
})

Mapbox GL directions plugin hiding search origin destination box

I am using Mapbox GL directions plugin inside my app where I set the origin on map load and set driving destination upon user click on any location on the map. I am now trying to remove the top left search origin / destination box yet after extensive research can't figure out how to do so, can someone please help by telling me how to do so? Thanks.
Code I am using in my app below:
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v8',
center: [userCoordinates.coords.longitude, userCoordinates.coords.latitude],
zoom: 15
});
var directions = new mapboxgl.Directions({
unit: 'metric',
profile: 'driving'
});
map.addControl(directions);
directions.setOrigin([userCoordinates.coords.longitude, userCoordinates.coords.latitude]);
map.on('click', function(e) {
var features = map.queryRenderedFeatures(e.point, { layers: ['gsLayer'] });
if (!features.length) {
return;
}
var feature = features[0];
directions.setDestination([feature.geometry.coordinates[0], feature.geometry.coordinates[1]]);
});
I couldn’t figure this out either since there is no documentation, but finally I read through the mapbox-gl-directions.js file and I think I found out how to do it.
In your example, you should embed the controls like this in order to remove the origin / destination box:
var directions = new mapboxgl.Directions({
unit: 'metric',
profile:'driving',
container:'directions', // Specify an element thats not the map container.
// UI controls
controls: {
inputs: false,
instructions: true
}
});
map.addControl(directions);
I'll assume you are using Mapbox GL Javascript, and looking at this example it appears map.addControl(new mapboxgl.Directions()); is what is adding the controller. Within your code you gave you also have this map.addControl(directions);. Try removing it and see what happens.
Hope this helps!

reproject map extent in openlayers 3

I want to set an extend on my Openlayers 3.9.0 map.
When the page loads, I want the map to already be centered in that extend, no matter the layers. So I guess I will set an extend to the view, right?
Map contains a single OSM layer like
var layer = new ol.layer.Tile({
source: new ol.source.OSM(
{
attributions: [
new ol.Attribution({
html: 'All maps © ' +
'OpenCycleMap'
})
]
}
),
opacity: 0.8,
brightness: 0.8
});
Then I set the view
var center = ol.proj.transform([21.54967, 38.70250], 'EPSG:4326', 'EPSG:3857');
var view = new ol.View({
center: center,
zoom: 6,
extent: [2297128.5,4618333.0 , 2459120.25,4763120.0]
});
And then the map
var map = new ol.Map({
target: 'map',
layers: [layer],
view: view,
});
I used my extend in an older project, with EPSG 900913. So to convert the extend from 900913 to default Openlayers 3 3857 I went here here and I put
2297128.5, 4618333 that convereted to 2297128.5,4618333.0
and then
2459120.25, 4763120that convereted to 2459120.25,4763120.0
my two problems
1- the converted coords look similar. Did I do something wrong?
2- the map is centered ok, but not zoomed in the extend. The coords define a county in Greece and the map does not zoom there, I see the whole Greece, along with Turkey and Italy.
What I did wrong? Thanks
Thanks everyone. What I did was
Keep the OSM layer as is.
Define the limits of the county. Turns out it was EPSG 900913
var countyLimits= ol.proj.transformExtent([2297128.5, 4618333, 2459120.25, 4763120], 'EPSG:900913', 'EPSG:3857');
View is now
var view = new ol.View({
center: center,
zoom: 6,
extent : countyLimits,
maxZoom:20
});
map is
var map = new ol.Map({
target: 'map',
layers:[layer],
view: view
});
After the map is defined, fit its view in the limits
map.getView().fit(countyLimits, map.getSize());
//get the view of the map and fit it to the limits, according to the map's size
fitExtend is now deprecated, so I used fit. It is experimental , but I guess it will become standard since it replaced fitExtend.
Thanks anyway people
Sources
OL answer
OL3 API
Several issues:
The extent [2297128.5,4618333.0, 2459120.25,4763120.0] seems to be in EPSG 3857 already and there is no need to transform it.
The extent option of ol.View is experimental and does not seem to work well. You can do the following to set the bounding box (after you declare map):
var extent = [2297128.5, 4618333.0, 2459120.25, 4763120.0];
view.fitExtent(extent, map.getSize());
The initial zoom in your example was due to the zoom level set on the view (zoom: 6). Using fitExtent() should override the initial zoom level. You can remove the zoom, center and extent options from your view declaration.
By the way, regarding the http://cs2cs.mygeodata.eu/ site, it seems that you have to specify EPSG:4326 instead of EPSG:900913 for the input coordinate, for the transformation to work correctly.
Note: ol.View.fitExtent() was renamed to ol.View.fit() in OpenLayers v3.7.0
It can be as easy as:
var min = [2297128.5, 4618333.0];
var max = [2459120.25, 4763120.0];
var extent = ol.extent.boundingExtent([min, max]);
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.fromLonLat([21.54967, 38.70250]),
zoom: 3,
extent: extent
})
});
http://jsfiddle.net/jonataswalker/zc3uL66q/

OpenLayers 3 - change base map from ol.layer.Tile (Bing) to ol.layer.Image (static image)

I need high-res map images for my application (solar power system design). Bing Maps in OL is good for finding the right building, but too low-res for laying out solar panels. So, I want to use a small high-res static map for doing the layout. Here's what I have currently. First load the Bing Maps layer:
var layers = [];
var baseBingMapLayer = new ol.layer.Tile({
source: new ol.source.BingMaps({
key: 'XXXXX',
imagerySet: 'AerialWithLabels',
})
});
layers.push(baseBingMapLayer);
var map = new ol.Map({
layers: layers,
target: 'map',
view: new ol.View({
center: [-13569845.9277,4485666.89612],
zoom: 5,
})
});
Then when I want to load the static map, the strategy is to remove the Bing Maps layer and then add the static image layer. I'm doing the following:
var extent = [0, 0, 1024, 768];
var projection = new ol.proj.Projection({
code: 'xkcd-image',
units: 'pixels',
extent: extent
});
var staticURL =
"https://maps.googleapis.com/maps/api/staticmap"
+ "?center=37.7431569802915,-121.4451930197085&"
+ "zoom=20&size=1024x768&scale=2&zoom=3&"
+ "format=jpg&maptype=satellite"
+ "&key=XXX";
map.removeLayer(baseBingMapLayer);
var imageLayer = new ol.layer.Image({
source: new ol.source.ImageStatic({
url: staticURL,
imageSize: [1024,768],
projection: projection,
imageExtent: extent
})
});
var imageLayerView = new ol.View({
projection: projection,
center: ol.extent.getCenter(extent),
zoom: 2
});
map.addLayer(imageLayer);
map.addView(imageLayerView);
Needless to say, this isn't working. I just get a blank screen with no exceptions thrown.
I actually had some success using jQuery to just empty the entire map div and start over with a new map object. However this seems to cause other problems and didn't seem like the right approach to me.
I'm going to continue working on this problem, but thought I would post since I'm sure I won't be the last person to try this little stunt :-)
Gary