How to get features in openlayers with mapbox? - webgl

I try to do it but it doesn't work, below is my main code.
enter image description here
enter image description here

You need to query the features on the Mapbox map
map.on('click', (e) => {
const point = new mapboxgl.Point(e.pixel[0], e.pixel[1]);
const features = mbMap.queryRenderedFeatures(point);
console.log(features);
});
https://codesandbox.io/s/mapbox-layer-forked-x8mocy?file=/main.js

Related

Draw LineString using webgl

How can I draw a LineString using WebGL over Openlayers 3 map? Please guide.
I have gone through below links which didn't help:
http://openlayers.org/en/master/examples/icon-sprite-webgl.html
http://openlayers.org/en/master/examples/symbol-atlas-webgl.html
You can easily add the Draw interaction to the map, as it is shown in some Openlayers 3 examples:
https://openlayers.org/en/latest/examples/draw-features.html
https://openlayers.org/en/latest/examples/draw-and-modify-features.html
https://openlayers.org/en/latest/examples/draw-freehand.html
You only have to create a Vector Layer and Draw Interaction with a shared vector source, and add them to the map:
var drawSource = new ol.source.Vector({wrapX: false});
var drawVector = new ol.layer.Vector({
source: drawSource
});
var draw = new ol.interaction.Draw({
source: drawSource,
type: 'LineString'
});
drawVector.setMap(map);
map.addInteraction(draw);
You will find an example in this jsfiddle

OL3: Clustering Vector Features when can't determine Feature type

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.

Open layer 3 click on layer best practice

I am new to OL.
I need to implement a logic that should happen if I pressed on a specific item in a specific layer.
I have to state that I'm not writing a project from scratch, and I actually inherited a very basic but complex system.
The system gets the layers from MapGuide 2.5.
This is how the map is initiated:
var map = new ol.Map({
loadTilesWhileInteracting:true,
layers: this.layers,
target: this._element[0],
controls: controls,
interactions: interactions,
view: view
});
view.fit(that.extent, map.getSize());
I tried adding a select interaction - it didn't work (my promise was never called).
var select_interaction = new ol.interaction.Select();
select_interaction.getFeatures().on("add", function (e) {
var feature = e.element; //the feature selected
});
map.addInteraction(select_interaction);
I tried:
map.on('click', function (evt) {
var feature = map.forEachFeatureAtPixel(evt.pixel,
function (feature, layer) {
debugger;
this.log("fff")
});
});
In this case, the promise works but I get no features.
EDIT:
I also tried:
var feature = map.forEachLayerAtPixel(evt.pixel,
function (feature, layer) {..}
but I get the exception:
uncaught security error: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data. ol.js:341
How can I do this?
Thanks,
Ido
I was getting the same error while I was trying to loop through layers at pixel via forEachLayerAtPixel method.
Thanks to #kagelos comment, I managed to solve the problem simply by filtering the layers and looping through only Vector layers.
Layer types are roughly separated in two categories in OL. Image layers (tiles etc.) and vector layers. You have to inspect the contents of this.layers that you pass as an argument in the constructor of the map and see what type of layers it contains. You can only interact directly with vector type layers.
Here is the final code:
Map.forEachLayerAtPixel( cursorPosition, function ( _layer ) {
// you will get the vector layer here
}, this, function ( _layer ) {
if ( _layer instanceof ol.layer.Vector ) {
return true;
}
});

How to export a featureOverlay drawn on openlayers3 map (projection EPSG:3857) to a KML file projected to EPSG:4326

I am drawing polygons on a featureOverlay attached to openlayers3 map (projection EPSG:3857) as follows:
// create openlayers3 map
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'sat'})
})
],
target: 'map',
view: new ol.View({
center: [-11000000, 4600000],
zoom: 4
})
});
// create the featureOverlay to receive polygons
var featureOverlay = new ol.FeatureOverlay();
featureOverlay.setMap(map);
// create the tool to draw polygons
draw = new ol.interaction.Draw({
features: featureOverlay.getFeatures(),
type: 'Polygon'
});
map.addInteraction(draw);
Until here, everything is ok! The idea is from oficial Draw features example. The next step is to export features drawn on the map to a KML file using projection EPSG:4326. I have tried to reach this task through the following code:
$('#download-button').click(function() {
// get the features drawn on the map
var features = featureOverlay.getFeatures().getArray();
// create an object to write features on a output KML file
var format = new ol.format.KML();
// write features to KML format using projection EPSG:4326
var kml = format.writeFeatures(features, 'EPSG:4326', 'EPSG:3857');
// Save KML node as KML file using FileSaver.js script
var str = (new XMLSerializer).serializeToString(kml);
var blob = new Blob([str], {type: "text/plain;charset=utf-8;"});
saveAs(blob, "NovaCamada.kml");
});
The main problem is KML file result always contains features with vertices on metrics units (I need degrees units!) even when shows the KML file on EPSG:4326.
The worst (and the purpose of my question) is that even when I change the piece of code that writes features to kml format to:
var kml = format.writeFeatures(features);
or:
var kml = format.writeFeatures(features, 'EPSG:3857', 'EPSG:4326');
the result is the same and nothing changes!
I expect ol.format.KML class converts the features from EPSG:3857 to EPSG:4326. Am I on the right way?
Do I need apply any reprojection on features before format it? Someone please could help me with this task?
Did I make myself clear?
P.S.: FileSaver.js
writeFeatures takes, as the 2nd argument, an object literal with two properties: dataProjection and featureProjection.
The KML format has a default dataProjection, EPSG:4326. This means you only need to specify the featureProjection in your case:
var result = kmlFormat.writeFeatures(features, {featureProjection: 'EPSG:3857'});
Unrelated note: we are changing the return type of writeFeatures in OpenLayers 3.1.0. writeFeatures will always return a string, for any format. This means you won't need to serialize the result of writeFeatures yourself with XMLSerializer.

Adding markers from a SQL db to OSM

I'm new to OpenStreetMap and I've been browsing the wiki and the net and I can't seem to find a tutorial anywhere but I've seen examples on the net.
Basically I want to generate my own OpenStreetmap and plot markers taking the latitude and longitude from a MySQL database and plotting them on my map. When the user clicks on a mark I'd like to have a popup. Basically I want this http://code.google.com/apis/maps/articles/phpsqlajax.html but for OpenStreetMap and not Google-maps.
Looks like they are using openLayer for map rendering. Here are some examples and api docs.
http://openlayers.org/dev/examples/
http://trac.osgeo.org/openlayers/wiki/Documentation
To accomplish this, you need to figure out the javascript for presenting markers on a "slippy map" interface.
OpenLayers is the name of a popular javascript library. It's free and open source. It's used to display a slippy map on the OpenStreetMap.org homepage, and various other sites around the web. It's often confused with OpenStreetMap itself, or people mistakenly get the impression that you must use OpenLayers if you want to embed OpenStreetMap maps on your site. Not true. There's lots of alternative javascript libraries for displaying a slippy map
...including the google maps API! You can set up a google maps display, but show OpenStreetMap "tile" images instead of google tiles. See Google Maps Example. This has the advantage of code compatibility, meaning you could follow through google maps tutorial you've linked there, but then drop in a cheeky bit of code to specify OpenStreetMap as the tile layer.
This has the disadvantage of showing an big evil google logo, and requiring an even more evil google maps API key, so all the cool kids are using OpenLayers.
There's various examples of using OpenLayers on the OpenStreetMap wiki. The "OpenLayers Dynamic POI" example shows the use of database for markers (although that example is a bit convoluted). Another popups example on my site
Hope that helps
// Sample code by August Li
// Modified by Tom Moore to work with SQL
var zoom, center, currentPopup, map, lyrMarkers;
var popupClass = OpenLayers.Class(OpenLayers.Popup.FramedCloud, {
"autoSize": true,
"minSize": new OpenLayers.Size(300, 50),
"maxSize": new OpenLayers.Size(500, 300),
"keepInMap": true
});
var bounds = new OpenLayers.Bounds();
var lat=36.287179515680556;
var lon=-96.69170379638672;
var zoom=11;
var lonLat = new OpenLayers.LonLat(lon, lat).transform(
new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));
// begin addMarker function
// info1 I was going to use to add a tooltip. Haven't figured out
// how to do that in OpenLayers yet :( Someone who knows share that with us
// iconurl is the url to the png file that you want to use for the icon.
// you MUST call addMarker at least once to initialize the map
function addMarker(lat, lng, info, info1, iconurl) {
// First check to see if the map has been initialized. If not, do that now ...
if (map == null) {
var options = {
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326"),
units: "m",
numZoomLevels: 19,
maxResolution: 156543.0339,
maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34)
};
map = new OpenLayers.Map("map", options);
map.addControl(new OpenLayers.Control.PanZoomBar());
var lyrOsm = new OpenLayers.Layer.OSM();
map.addLayer(lyrOsm);
lyrMarkers = new OpenLayers.Layer.Markers("Markers");
map.addLayer(lyrMarkers);
//add marker on given coordinates
map.setCenter(lonLat, zoom);
zoom = map.getZoom();
}
var iconSize = new OpenLayers.Size(36, 36);
var iconOffset = new OpenLayers.Pixel(-(iconSize.w / 2), -iconSize.h);
var icon = new OpenLayers.Icon(iconurl, iconSize, iconOffset);
var pt = new OpenLayers.LonLat(lng, lat).transform(
new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
bounds.extend(pt);
var feature = new OpenLayers.Feature(lyrMarkers, pt);
feature.closeBox = true;
feature.popupClass = popupClass;
feature.data.popupContentHTML = info;
feature.data.overflow = "auto";
var marker = new OpenLayers.Marker(pt, icon.clone());
var markerClick = function(evt) {
if (currentPopup != null && currentPopup.visible()) {
currentPopup.hide();
}
if (this.popup == null) {
this.popup = this.createPopup(this.closeBox);
map.addPopup(this.popup);
this.popup.show();
} else {
this.popup.toggle();
}
currentPopup = this.popup;
OpenLayers.Event.stop(evt);
};
marker.events.register("mousedown", feature, markerClick);
lyrMarkers.addMarker(marker);
}
// end addMarker function
Best regards! I hope this helps someone who needs this to work...

Resources