mapbox GL JS - pass source data to custom layer - mapbox-gl-js

I've added some quads with custom shaders to map (Examples are here and here). I need to pass data from my source to shader. Tutorials says that I can just pass 'source': 'point', to layer class constructor. Is it possible to pass source data to custom layer?
Here is source example:
map.addSource('point', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [0, 0]
}
}
]
}
});

Related

Is there a way that I can connect a polygon format (JS) to a map (HTML)

I'm trying to put a polygon format from Mapbox into the Mapbox map itself (via a Github copy for a project), and I haven't yielded any results.
I did the formatting, using different files, combining them into 1 via a combiner, etc.
Polygon (JS):
map.on('load', () => {
// Add a data source containing GeoJSON data.
map.addSource('maine', {
'type': 'geojson',
'data': {
'type': 'Feature',
'geometry': {
'type': 'Polygon',
// These coordinates outline Maine.
'coordinates': [
[
[-125.15625000000001, 48.04870994288686],
[-124.71679687499999, 43.32517767999296],
[-125.15625000000001, 39.639537564366684],
[-121.11328124999999, 34.59704151614417],
[-121.11328124999999, 34.59704151614417],
[-117.158203125, 32.47269502206151],
[-105.732421875, 31.27855085894653],
[-97.20703125, 25.64152637306577],
[-84.287109375, 29.84064389983441],
[-80.947265625, 24.84656534821976],
[-74.970703125, 35.38904996691167],
[-66.62109375, 45.02695045318546],
[-68.73046875, 47.39834920035926],
[-71.455078125, 44.84029065139799],
[-82.880859375, 41.96765920367816],
[-88.154296875, 48.22467264956519],
[-109.072265625, 49.03786794532644],
[-123.134765625, 49.15296965617042],
[-125.15625000000001, 48.04870994288686],
]
]
}
}
});
// Add a new layer to visualize the polygon.
map.addLayer({
'id': ' ',
'type': 'fill',
'source': 'maine', // reference the data source
'layout': {},
'paint': {
'fill-color': '#0080ff', // blue color fill
'fill-opacity': 0.2
}
});
// Add a black outline around the polygon.
map.addLayer({
'id': 'outline',
'type': 'line',
'source': 'maine',
'layout': {},
'paint': {
'line-color': '#000',
'line-width': 0
}
});
});
Said remaining copies of code are located in https://github.com/AliCodes-Beep/Google-Map-Clone

MapBoxGL - why does it flag my source as invalid geoJSON

I am trying to dynamically add polygons to a MapboxGL map by passing the coordinates into a funciton. Should be simple enough, but I'm having a tough time with it. Why does this work...
map.addSource('zip_code', {
'type': 'geojson',
'data':
{
'type':'Feature',
'geometry':
{
'type': 'Polygon',
'coordinates': [[[-94.853056,38.956395],[-94.851164,38.956397],[-94.849007,38.955712],[-94.849826,38.954964],[-94.851949,38.954824],[-94.852459,38.953593],[-94.85233,38.94554],[-94.851999,38.944495],[-94.848298,38.941805],[-94.844247,38.941655],[-94.843825,38.942708],[-94.843982,38.950197],[-94.844067,38.959505],[-94.844526,38.960942],[-94.8436,38.96136],[-94.842219,38.963486],[-94.843687,38.963468],[-94.844052,38.964628],[-94.844389,38.972774],[-94.844171,38.974898],[-94.838256,38.974272],[-94.838265,38.976055],[-94.836484,38.976063],[-94.836478,38.978123],[-94.844112,38.978049],[-94.844088,38.981676],[-94.825422,38.981609],[-94.821139,38.981585],[-94.821069,38.985312],[-94.816327,38.985269],[-94.80934,38.985137],[-94.810772,38.981613],[-94.809256,38.979913],[-94.807271,38.975244],[-94.804835,38.975174],[-94.803266,38.976119],[-94.801335,38.974898],[-94.7977,38.975117],[-94.797298,38.974488],[-94.797313,38.970997],[-94.797375,38.955914],[-94.795936,38.955915],[-94.797378,38.954629],[-94.797477,38.94162],[-94.807256,38.941881],[-94.812495,38.942072],[-94.816146,38.942039],[-94.830418,38.941388],[-94.852979,38.941395],[-94.853353,38.956395],[-94.853056,38.956395]]]
}
}
});
...but this doesn't with an error of: "Input data given to 'xyz' is not a valid GeoJSON object."
var data = "[[[-94.853056,38.956395],[-94.851164,38.956397],[-94.849007,38.955712],[-94.849826,38.954964],[-94.851949,38.954824],[-94.852459,38.953593],[-94.85233,38.94554],[-94.851999,38.944495],[-94.848298,38.941805],[-94.844247,38.941655],[-94.843825,38.942708],[-94.843982,38.950197],[-94.844067,38.959505],[-94.844526,38.960942],[-94.8436,38.96136],[-94.842219,38.963486],[-94.843687,38.963468],[-94.844052,38.964628],[-94.844389,38.972774],[-94.844171,38.974898],[-94.838256,38.974272],[-94.838265,38.976055],[-94.836484,38.976063],[-94.836478,38.978123],[-94.844112,38.978049],[-94.844088,38.981676],[-94.825422,38.981609],[-94.821139,38.981585],[-94.821069,38.985312],[-94.816327,38.985269],[-94.80934,38.985137],[-94.810772,38.981613],[-94.809256,38.979913],[-94.807271,38.975244],[-94.804835,38.975174],[-94.803266,38.976119],[-94.801335,38.974898],[-94.7977,38.975117],[-94.797298,38.974488],[-94.797313,38.970997],[-94.797375,38.955914],[-94.795936,38.955915],[-94.797378,38.954629],[-94.797477,38.94162],[-94.807256,38.941881],[-94.812495,38.942072],[-94.816146,38.942039],[-94.830418,38.941388],[-94.852979,38.941395],[-94.853353,38.956395],[-94.853056,38.956395]]]";
map.addSource('zip_code', {
'type': 'geojson',
'data':
{
'type':'Feature',
'geometry':
{
'type': 'Polygon',
'coordinates': data
}
}
});
I have tried about everything to dynamically set that source for a variable with no luck.

Mapbox GeoJSON or Plain Lat and Long for Database Storage

I am new to working with maps. My issue is I don't understand if I need to store data in my database as geoJSON or just store the coordinates and create custom markers with popups which is what I need to do. My database is MongoDB, although it shouldn't really matter for this. In geoJSON Mapbox parses the data like so:
const geojson = {
'type': 'FeatureCollection',
'features': [
{
// feature for Mapbox DC
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [
-77.03238901390978, 38.913188059745586
]
},
'properties': {
'title': 'Mapbox DC'
}
},
{
// feature for Mapbox SF
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-122.414, 37.776]
},
'properties': {
'title': 'Mapbox SF'
}
}
]
}
The example data
map.current.addSource('points', {
'type': 'geojson',
'data': geojson
});
The data being parsed (part of the code, it's in load image for the custom markers thing I was talking about it.)

Routing between two points in Mapbox

I am using MapBox to create a route between two points. I have LatLng of two points already and have successfully added Markers at source and destination points.
The problem is how to map or connect between these two points using curved lines (route) when the user clicks on the source point?
e.g flights routes map
If you want to draw arcs lines that connect 2 points on the earth surface, you do not have to worry about the curvature, as the shortest line between 2 points on a sphere is curved.
The below should do the trick and draw a curved line between San Francisco and Washington DC on your Mapbox GL JS map:
// San Francisco
var origin = [-122.414, 37.776];
// Washington DC
var destination = [-77.032, 38.913];
// A simple line from origin to destination.
var route = {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'LineString',
'coordinates': [origin, destination]
}
}
]
};
map.on('load', function () {
// Add a source and layer displaying a point which will be animated in a circle.
map.addSource('route', {
'type': 'geojson',
'data': route
});
map.addLayer({
'id': 'route',
'source': 'route',
'type': 'line',
'paint': {
'line-width': 2,
'line-color': '#007cbf'
}
});
});

Cusotm markers in mapbox gl js does not work?

I'm trying to add custom markers to a mapbox map using the example from their site https://docs.mapbox.com/mapbox-gl-js/example/geojson-markers/ but everytime I replace their link with mine (same photo format) or any link, it does not matter, the photo does not render, if anyone is able to show me a working example with a custom photo/marker. I need it to work using this example, I was able to add custom markers in another way but I need this specific way with .addSource and .addLayer
mapboxgl.accessToken = 'pk.eyJ1IjoibWFya2V0aW5nYnNvIiwiYSI6ImNrYnYwZmk3YjAxZjgyem1wY2Zmc3F4Y2EifQ.gMF-eCCaAHHgWIUoRcnfkg';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
center: [-96, 37.8],
zoom: 3
});
map.on('load', function() {
// Add an image to use as a custom marker
map.loadImage(
'https://docs.mapbox.com/mapbox-gl-js/assets/custom_marker.png', //here is the problem if i try to replace the image
function(error, image) {
if (error) throw error;
map.addImage('custom-marker', image);
// Add a GeoJSON source with 2 points
map.addSource('points', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [
{
// feature for Mapbox DC
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [
-77.03238901390978,
38.913188059745586
]
},
'properties': {
'title': 'Mapbox DC'
}
},
{
// feature for Mapbox SF
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-122.414, 37.776]
},
'properties': {
'title': 'Mapbox SF'
}
}
]
}
});
// Add a symbol layer
map.addLayer({
'id': 'points',
'type': 'symbol',
'source': 'points',
'layout': {
'icon-image': 'custom-marker',
// get the title name from the source's "title" property
'text-field': ['get', 'title'],
'text-font': [
'Open Sans Semibold',
'Arial Unicode MS Bold'
],
'text-offset': [0, 1.25],
'text-anchor': 'top'
}
});
}
);
});
Based on the documentation of map.loadImage, if you are loading that image from an External domain, that domain must support CORS (Cross-Origin Resource Sharing).
As you are not including what's the image your are trying to load, I cannot verify it, but it seems it's related to that.
EDITED: if you need a CORS-enabled server to upload your image, you can try to use any of the available image uploader servers such as https://postimg.cc/. but I wouldn't recommend this approach beyond a simple PoC.
I have tried your code with this image
and I have created a fiddle with it on how to add a custom image for a marker... and it works, so as said the code is right but the issue you are experiencing is because the image you are trying to use is not hosted in a CORS enabled domain.
If this solution solves your issue, please mark it as 'answer accepted', this way will also help other users to know it was the right solution.