Is there a way to use more than one property in a property function in Mapbox GL JS? In CartoCSS, I would do something like the following:
.states {
[name="California"] {
"polygon-fill": "blue"
},
[name_abbrev="WA"] {
"polygon-fill": "green"
}
}
In Mapbox GL JS it seems that I can style the fill-color based on either the property name -or- name_abbrev, but not a combination of two properties. For example:
'fill-color': {
'property': 'name',
'type': 'categorical',
'stops': [
['California', 'blue']
]
},
'fill-color': {
'property': 'name_abbrev',
'type': 'categorical',
'stops': [
['WA', 'green']
]
}
This results in the second fill-color overriding the first, and California would simply be green.
Mapbox GL does not support styling based on multiple properties within one layer. You could rework your data to combine the properties based on which you'd like to style into one layer, or you could create two layers and use filters to separate features, if your reasoning is that not all features have a certain layer/some need to use a fallback property: something like
{
... layer metadata (id, source, source-layer, type, etc) ...
'filter': ['has', 'name'],
'paint': {
'fill-color': {
'property': 'name',
'type': 'categorical',
'stops': [
['California', 'blue']
]
}
}
},
{
... layer metadata (id, source, source-layer, type, etc) ...
'filter': ['!has', 'name'],
'paint': {
'fill-color': {
'property': 'name_abbrev',
'type': 'categorical',
'stops': [
['WA', 'green']
]
}
}
}
Related
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
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.)
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]
}
}
]
}
});
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.
Here's what I mean.
Take a look at the following screenshot from foursquare:
However, using street view, here's what that same area looks like in my map at the same zoom level:
As you can see, the buildings don't show up. How can I make these buildings show up?
If you use mapbox gl-js API than I might know the solution.
I think you need to add another layer, I did it like this(add the code below to your client-side javascritpt file):
`map.on('load', function () {
map.addLayer({
'id': '3d-buildings',
'source': 'composite',
'source-layer': 'building',
'filter': ['==', 'extrude', 'true'],
'type': 'fill-extrusion',
'minzoom': 14,
'paint': {
'fill-extrusion-color': '#aaa',
'fill-extrusion-height': {
'type': 'identity',
'property': 'height'
},
'fill-extrusion-base': {
'type': 'identity',
'property': 'min_height'
},
'fill-extrusion-opacity': .6
}
});
});`