QuerySourceFeature is not working as expected - Mapbox GL - javascript

I am looking for a answer that will solve my problem. I am highlighting an address based on geocoder searched coordinates. This same functionality is working perfect on the click on building but I do not want to click on building rather just highlight the building based on searched coordinates. I am providing code below:
map.addLayer(
{
id: "3d-buildings",
source: "composite",
"source-layer": "building",
type: "fill",
minzoom: 10,
paint: {
"fill-color": "#aaa",
},
},
labelLayerId
);
map.addSource("currentBuildings", {
type: "geojson",
data: {
type: "FeatureCollection",
features: [],
},
});
map.addLayer(
{
id: "highlight",
source: "currentBuildings",
type: "fill",
minzoom: 15,
paint: {
"fill-color": "#f00",
},
},
labelLayerId
);
This below click working perfect
map.on("click","3d-buildings", (e) => {
map.getSource("currentBuildings").setData({
type: "FeatureCollection",
features: e.features,
});
});
I want the same features but not on click rather than on geocoder result coordinates:
geocoder.on("result", (e) => {
var coordinates = e.result.geometry.coordinates;
const selectedFeatures = map.querySourceFeatures(coordinates, {
layers: ["3d-buildings"],
});
console.log(selectedFeatures); //giving blank array, how can I get the features same as the onclick function is providing with additional parameter which is 3d-buildings
map.getSource("currentBuildings").setData({
type: "FeatureCollection",
features: e.features,
});
});
Maybe I am wrong at some point in using querySourceFeature. Please direct me in right direction.

Related

Is there any way to update my mapbox gl source?

Hello i have a problem when i try to update my mapbox source on click.
I have already to sources (cells , heatmap), I try to add a new sources with these code
this.map.addSource("points", {
type: "geojson",
data: {
type: "Feature",
geometry: {
type: "Point",
coordinates: [-77.0323, 38.9131],
},
properties: {
title: "Mapbox DC",
"marker-symbol": "monument",
},
},
});
I also try delele sources (cells , heatmap), add then a dd a new sources.
this.map.removeLayer("heatmap");
this.map.removeSource("heatmap");
this.map.removeLayer("cells");
this.map.removeSource("cells");
this.map.addSource("points", {
type: "geojson",
data: {
type: "Feature",
geometry: {
type: "Point",
coordinates: [-77.0323, 38.9131],
},
properties: {
title: "Mapbox DC",
"marker-symbol": "monument",
},
},
});
I don't get any error in the browser console from mapbox but i cant see the new sources.
Thanks a lot !
I find the solution i have wrong coordinates ( i have lat,lot but we want lot,lat) –

How to retrieve data from JSON file without manually entering the data mapbox

I want to use a JSON file containing coordinates to plot points on a map with Mapbox and add markers at those locations. I've followed a few of their tutorials and searched elsewhere (stack overflow, Github etc) to see if I could find a solution but nothing seemed to work. I'm not getting any errors when I open the HTML file in the browser but the markers aren't appearing on the map at the JSON's coordinates and I'm not really sure how to get the JSON's coordinates to be read and then plotted on the map. I want the JSON to be used from the same folder as the project and not a URL so this didn't work for me either.
<script>
mapboxgl.accessToken = 'pk.eyJ1Ijoiam1hcHNkamFuZ28iLCJhIjoiY2tydzIwazc4MGNnODJvb2VhNHNhZDd5diJ9.iwGIdgMHrcjbNu1xJRAElQ';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
// style: 'mapbox://styles/mapbox/light-v10',
center: [-0.19346, 51.50405],
zoom: 9
});
map.on('load', () => {
map.addLayer({
id: 'restaurants',
type: 'Point',
source: {
type: 'geojson',
data: './restaurants.json' // replace this with the url of your own geojson
},
paint: {
'circle-radius': [
'interpolate',
['linear'],
['number', ['get', 'coordinates']],
0,
4,
5,
24
],
'circle-color': [
'interpolate',
['linear'],
['number', ['get', 'coordinates']],
0,
1,
2,
3,
4,
5,
],
'circle-opacity': 0.8
}
});
});
I don't know if this is your only error, but this line:
type: 'Point',
should be:
type: 'circle',

Mapbox, bounce corresponding marker when hovering over sidebar element

I want to highlight a marker on a map, when I hover the correspondent item on a sidebar.
I have the same items showing in the map, and also on a side bar.
So i want that whem you hover over a item on a sidebar, the corresponding marker bounces, or moves or does something.
I have a map.on('load', function() {...}
Where i load a source markers, activate culsters, and add some layers,
The source is a geojson file I build with data from my backend.
Where i load a source, activate culsters, and add some layers:
map.on('load', function() {
map.addSource('users', {
type: "geojson",
data: markers,
cluster: true,
});
map.addLayer({
id: "singles",
type: "circle",
source: "users",
filter: ["!has", "point_count"],
paint: {
'circle-radius': {
'base': 10,
'stops': [[5, 20], [15, 500]]
},
'circle-color': '#ddffc8',
}
});
map.addLayer({
id: "clusters",
type: "circle",
source: "users",
filter: ["has", "point_count"],
paint: {
"circle-color": '#ddffc8',
'circle-radius': {
'base': 10,
'stops': [[5, 20], [15, 500]]
},
}
});
map.addLayer({
id: "cluster-count",
type: "symbol",
source: "users",
filter: ["has", "point_count"],
layout: {
"text-field": "{point_count_abbreviated}",
"text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Bold"],
"text-size": 12
}
})
})
I can acces the GeoJson, but its only a json file with the info of each of the markers, there is no property in it like for example marker.bounce or so...
So, how can I make it so that when i hover over a sidebar item, the corrresponding markers bouces, or changes icon or does something?
Thanks.

How to display individual feature popup on mapbox

I've got a map and have created a feature layer like this:
window.map = L.mapbox.map('map', 'example.wefk232sm')
.setView([homeLatitude, homeLongitude], initialZoom);
var myLayer = L.mapbox.featureLayer().addTo(map);
// Pass features to the map
myLayer.setGeoJSON(geoJson);
The geoJson object looks like this:
var geoJson = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {
title: name,
other: "text",
'marker-color': '#54a743',
'stroke': '#428334',
url: link
},
geometry: {
type: 'Point',
coordinates: [longitude, latitude]
}
]
};
What I'm trying to do is open the popup relating to a particular feature from, say the name on the geoJson.features[0].properties object, but I can't work out how to do this.
I can access it on click with this:
myLayer.on('click', function(e) {
e.layer.openPopup();
});
Mapbox is v1.6.2
You should be able to grab properties.title, for example, with the following
myLayer.on('click', function(e) {
var title = e.layer.feature.properties.title;
// do something with the title
});

Openlayers projection with OSM style maps and a GeoJSON vector layer

Note: I know there's another question similar to this but it hasn't been answered and I need to know how mixed projections can be dealt with with GeoJSON and OSM.
I'm so confused. I was using the OSMDroid API on Android for mapping and wanted to replicate it using OpenLayers and GeoExt, but I've got a projection problem with including GeoJSON nodes and action events.
My tile set is OSM based, and is hosted on the same Web server as this HTML/JS. See it all below. I realize my boundaries aren't working, and my projections might be completely wrong. I've been testing different combinations.
The problem is my map displays correctly and is centered fine. However:
My GeoJSON feature nodes are way off the map. They're in a different projection long/lat, but I don't know how to set or convert GeoJSON long/lat to the current map projection.
My mapCtrl doesn't work. When I click it the lonlat is another projection (the OSM projection coords) and I can't seem to convert them)
Any tips on how extent/bounds actually work would be greatly appreciated
Can someone please help with a bit of projection advice? Sigh... I'm not patient enough for this.
Here's my full JS, as is:
var mapPanel, store, gridPanel, mainPanel, nodePop, mapPop;
Ext.onReady(function() {
var map, mapLayer, vecLayer;
var lon = -70.885610;
var lat = 38.345822;
var zoom = 17;
var maxZoom = 18;
var toProjection = new OpenLayers.Projection("EPSG:4326");
var fromProjection = new OpenLayers.Projection("EPSG:900913");
var extent = new OpenLayers.Bounds(-1.32,51.71,-1.18,51.80).transform(fromProjection, toProjection);
// Setup the node layer feature store and push it all into a vector layer
vecLayer = new OpenLayers.Layer.Vector("vector");
store = new GeoExt.data.FeatureStore({
layer: vecLayer,
fields: [
{name: 'name', type: 'string'},
{name: 'status', type: 'string'}
],
proxy: new GeoExt.data.ProtocolProxy({
protocol: new OpenLayers.Protocol.HTTP({
url: "data/sa.json",
format: new OpenLayers.Format.GeoJSON()
})
}),
autoLoad: true
});
// Setup the basic map layer using OSM style tile retreival to pull tiles
// from the same server hosting this service
map = new OpenLayers.Map(
'map', {
controls:[
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.PanZoomBar(),
new OpenLayers.Control.Attribution(),
new OpenLayers.Control.ScaleLine()],
projection: toProjection,
displayProjection: fromProjection,
numZoomLevels: 20,
fractionalZoom: true
});
mapLayer = new OpenLayers.Layer.OSM(
"Local Tiles",
"tiles/${z}/${x}/${y}.png",
{
zoomOffset: 17,
resolutions: [1.194328566741945,0.5971642833709725,0.2985821416854863] // Zoom level 17 - 19
});
map.addLayers([mapLayer, vecLayer]);
// Create a map panel
mapPanel = new GeoExt.MapPanel({
title: "Map",
region: "center",
map: map,
xtype: "gx_mappanel",
center: new OpenLayers.LonLat(lon, lat),
zoom: zoom
});
// Create a grid panel for listing nodes
gridPanel = new Ext.grid.GridPanel({
title: "Nodes",
region: "east",
store: store,
width: 275,
columns: [{
header: "Name",
width: 200,
dataIndex: "name"
}, {
header: "Status",
width: 75,
dataIndex: "status"
}],
sm: new GeoExt.grid.FeatureSelectionModel({
autoPanMapOnSelection: true
})
});
// Create the main view port
new Ext.Viewport({
layout: "border",
items: [{
region: "north",
contentEl: "title",
height: 150
}, mapPanel, gridPanel]
});
var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
map.setCenter(lonLat, zoom);
// Attach all the event driven stuff here...
// Create a node selection pop up control
function nodeAction(feature) {
nodePop = new GeoExt.Popup({
title: 'Node selected',
location: feature,
width: 200,
html: "",
maximizable: true,
collapsible: true
});
nodePop.on({
close: function() {
if(OpenLayers.Util.indexOf(vectorLayer.selectedFeatures, this.feature) > -1) {
selectCtrl.unselect(this.feature);
}
}
});
nodePop.show();
};
// Attach the pop to node/feature selection events
var selectCtrl = new OpenLayers.Control.SelectFeature(vecLayer);
vecLayer.events.on({
featureselected: function(e) {
nodeAction(e.feature);
}
});
// Create map selection pop up control
function mapAction(lonlat) {
mapPop = new GeoExt.Popup({
title: 'Map selected',
location: lonlat,
width: 200,
html: "You clicked on (" + lonlat.lon.toFixed(2) + ", " + lonlat.lat.toFixed(2) + ")",
maximizable: true,
collapsible: true,
map: mapPanel.map,
anchored: true
});
mapPop.doLayout();
mapPop.show();
};
var mapCtrl = new OpenLayers.Control.Click({
trigger: function(evt) {
var lonlat = mapPanel.map.getLonLatFromViewPortPx(evt.xy);
lonlat.transform(new OpenLayers.Projection("EPSG:4326"), mapPanel.map.getProjectionObject());
//.transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
mapAction(lonlat);
}
});
mapPanel.map.addControl(mapCtrl);
mapCtrl.activate();
});
// A control to handle user clicks on the map
OpenLayers.Control.Click = OpenLayers.Class(
OpenLayers.Control, {
defaultHandlerOptions: {
single: true,
double: false,
pixelTolerance: 0,
stopSingle: true
},
initialize: function(options) {
this.handlerOptions = OpenLayers.Util.extend(
options && options.handlerOptions || {},
this.defaultHandlerOptions
);
OpenLayers.Control.prototype.initialize.apply(
this, arguments
);
this.handler = new OpenLayers.Handler.Click(
this,
{ click: this.trigger },
this.handlerOptions
);
},
CLASS_NAME: "OpenLayers.Control.Click"
}
);
Here's the GeoJSON I'm using:
{
"type": "FeatureCollection",
"features": [
{
"geometry": {
"type": "Point",
"coordinates": [
-70.3856,
38.3458
]
},
"type": "Feature",
"properties": {
"name": "Node0",
"status": "Active",
"externalGraphic": "img/node2.png",
"graphicHeight": 75, "graphicWidth": 75
},
"id": 100
},
{
"geometry": {
"type": "Point",
"coordinates": [
-70.885810,
38.344722
]
},
"type": "Feature",
"properties": {
"name": "Node1",
"status": "Active",
"externalGraphic": "img/node2.png",
"graphicHeight": 75, "graphicWidth": 75
},
"id": 101
}
]
}
Ok, here's how I dealt with the issue:
I'm using the embedded the Jetty Web server in my back-end, but
regardless, I created a servlet to respond with GeoJSON format data.
Each Feature location lon/lat is converted between projections.
(e.g. EPSG:4326 to EPSG:900913)
The lon/lat projection conversation leveraged the GeoTools Java API.
This blog post was particularly helpful
(http://ariasprado.name/2012/08/13/quick-and-dirty-coordinate-transforming-using-geotools.html)
Note that you'll need to go through a fair bit of trial and error if
you only want to include the jars required for converting yout
projections. GeoTools is large, does a lot, and has a number of
jars.
Now when the GeoExt.data.ProtocolProxy loads my GeoJSON content it's already in OSM compatible EPSG:900913. I would have liked to deal with this entirely in GeoExt/OpenLayer, but there doesn't appear to be an easy way. I will acknowledge that GeoExt and OpenLayers don't have super great reference documentation to follow.
I'd include my GeoTools code but "Arias Prado GIS Ramblings" blog post above does a better job than I could. Again though, note that you'll have to trial and error the jars. Projection encoders are loaded dynamically, and they in turn have class dependencies from other jars.

Categories

Resources