MapBox GL - Render GeoJson Thematically Based on Data in Client - mapbox-gl-js

I have a geoJson layer showing U.S. states, with only an ID, and no other properties.
I also have a local array of data in memory with lots of properties about those states: things like population, acres of farmland, sales tax rate etc. One of the properties is the ID that's in the geoJson layer. So I should be able to join the local array with features in the geoJson layer.
I would like to be able to thematically style the states based on any of those properties, allowing the user the ability to choose the property. All the examples I have seen for thematic styling of GeoJson layers in MapBox require (1) that the properties exist in the geoJson itself, and (2) that you define the property and styling rules in advance (I'm not sure if there's a way to change this at a later point).
In other map libraries, I think including Leaflet, you can define a paint function, and pass in the feature. Is there anything like this in MapBox GL?
Thanks.

You can make your life easier by joining the geojson data with your "properties" data into a single geojson feature collection.
Once you got that going, you can use map.setPaintProperty(layerId, ...) to update the layer style based on user interaction: https://docs.mapbox.com/mapbox-gl-js/api/#map#setpaintproperty
As of the documentation:
value(any) The value of the paint property to set. Must be of a type appropriate for the property, as defined in the Mapbox Style Specification .
You can set anything the style spec supports, even interpolated data-driven properties, wich means you can set & update any property of the layer you would be able to configure when newly adding that layer. Sure, you can not set multiple paint/layout properties with a single call, but that is something you can easily abstract away yourself.
This might be a bit far fetched, but assuming what you call a "theme" is just a collection of paint properties and values which you derived from an user interaction. You can just encode your "theme" as a valid mapbox style and use map.setStyle(...) to efficiently change multiple properties with a single call. Remeber setStyle() can receive a a style url but also a complete style object.

Related

Is it possible to give each property in Mapbox a different color based on data that we have on the property?

Is it possible in the Mapbox GL JS to set a property color for each property? For each address we know if the property is an existing customer or not, so we would like to give properties of our customers a different color then the properties that are not our customers. Is something possible?
I already know how to set a color for all properties (followed this example: https://docs.mapbox.com/mapbox-gl-js/example/change-building-color-based-on-zoom-level/), but we like to have different colors based on the data that we have on the address/property.
Also wonder how we can map our data (address X is a customer) to a property in Mapbox GL JS.
Regards,
Nick

Is there a way to set multiple layer filters in the Mapbox Static Images API?

I am using the mapbox static images API. I have two layers in my style that I'm trying to filter on the request. The documentation seems to only provide a single "setfilter" and a single "layer_id" property, indicating I can only filter one of the layers.
Is it possible to filter two (or three, four) layers in the static images API? I'd love to be able to comma separate the layer_id and/or setfilter parameters in the request to handle this case.
An example request they provide in the docs for setting the filters is:
https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/-91,60,2/800x600?access_token=YOUR_MAPBOX_ACCESS_TOKEN&setfilter=["==","name_en","Canada"]&layer_id=country-label
I am looking for something like:
https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/-91,60,2/800x600?access_token=YOUR_MAPBOX_ACCESS_TOKEN&setfilters=["==","name_en","Canada"],["==","name","New York"]&layer_ids=country-label,state-label
FWIW, my current workaround is to use an overlay for one of the layers to form the geojson objects that I needed filtering, but its hacky and has an upperbound on how many I can add to the request, and I had to simplify the geojson for brevity in the request.
Unfortunately there is not a direct way to reference multiple layers in a request to the Static Images API.
As a workaround you may be able to create a new style layer in Mapbox Studio that combines all of the layers you want to apply a filter to. You could then use setfilter on that layer to achieve filtering across these multiple layers, see the documentation here.

Accessing nested properties of a TileSet

I am trying to access all the features of a specific tileset generated threw MapBoxStudio.
Reading the API doc I guess I should be able to get all the nested parameters from the method :
map.querySourceFeatures(IdOfMyLayer);
However, the output of this is empty.
map.querySourceFeatures('words');
Where 'words' is the ID of the layer I got from map.getStyle().layers
I would expect to get access to the properties of this particular layer.
However, I get an empty result.
Sorry for the noob question but I am missing something crucial here in the way MapBox is working, any help from you would be very much appreciated.
If you are trying to access all the features of a tileset that you created in Studio, you should probably consider a different workflow. By definition, a tileset is a transformation of a dataset optimised for displaying a map, not querying.
If you use a Mapbox dataset rather than a tileset, you can access the whole dataset as a clean GeoJSON object - assuming it's small enough to load into the browser. Alternatively, you could create a GeoJSON by some other means, then upload it.
If querySourceFeature() is returning [], then most likely no features have loaded in the current viewport (yet). Perhaps you need to trigger the call at a later time, when the source data has loaded.
I get it now.
The proper way to retrieve all the features of a dataset is to use the DataSet API:
https://docs.mapbox.com/api/maps/#retrieve-a-dataset
This is what I've done :
$.ajax({
url: 'https://api.mapbox.com/datasets/v1/*****/{dataset_id}/features?limit=50&access_token=********',
type:'GET',
success:function(data){console.log(data)},
error:function(error){console.log('ERROR')}
})
With the {dataset_id} taken from mapboxStudio.
I can limit and store the variable to process the JSON response.
Thanks a lot :)

Binding Text Blocks in a Master to Shape Data on the Master

I'm returning to Visio after being a power user in the 2000's. A lot of what I'd do back in the day was create custom masters and associate data with the shape with individual labels etc. on those masters. Sort of a multi-part shape bound to the shape data on a given master, with fine-tuned arrangement.
The shapesheet seems entirely gone in 2016 Pro and now we have the data graphic features, which are nice and interesting, but they don't give you the same degree of fine-tuning and baked-in support that my old approach of building custom masters did.
How would I go about taking a text block on a master and binding it inside that master to the master's shape data for a given property? I'm betting it's a custom expression, but I'm not sure what the syntax would be.
Oh, my overall use case here: I want to have a shape with fine-tuned fields that are always visible, but appear in different compartments on the shape. I want to link external data into the shape and have the text blocks pull the value out of the shape data and render it for the area in question. I may use Data Graphics for ancillary things on a case by case basis, but at a core, I know I want certain features to always be present in a master and styled in certain ways.
to display the property of another shape you need to reference it in the form:
sheet!N.prop.X
N being the ID of the other shape, in your case the parent.
Store this value in a intermediate field, the use insert/field.
Here's a tool to do this automatically: http://visguy.com/vgforum/index.php?topic=6318.0
To handle input options to custom properties I recommend the following
1) set up a custom property of the page as semi-colon separated list for holding the desired values. eg: prop.myOption = "A;B;C"
2) in the shape needing this option, set up am according field as fixed list. In the format cell write: thePage!prop.options.
That's it. This way you can edit the list in one central place and have all the shapes updated.

Meaning of the spatialite scheme generated by the spatialite_osm_map tool

I used the spatialite_osm_map tool to generate a spatialite database from an .osm.pbf file. After the process was finished, a series of tables were generated in the database as shown in the image.
I noticed that there were 3 groups of tables based on the prefixes of their names: In_, pg_ and pt_. I also noticed that the rest of the name corresponded to a key defined in OpenStreetMap.
Can someone explain to me how the information is distributed in each of these groups and tables? I've searched for a site that explains the resulting schema after the conversion, but I've only found information on how to use the tool.
I think you have already identified the key points of this scheme.
It's main purpose is to offer the data from OSM in a way who could be more direct and intuitive for a GIS user. The data is splited according to OSM tags (aerialway, aeroway, amenity, etc., you can change the list of tags to be used if you don't need all of them) and according to the type of geometry (pt_* for points, ln_* for lines, and pg_* for polygons) so these tables (which could be directly seen as "layers" by a GIS user) can quickly be styled (for example in a GIS desktop application such as QGIS) with simple rules due to this simple schema (for example one can set rules like green for pg_natural, blue for ln_waterway and pg_waterway, or just click on the "pg_building" layer to toggle its visibility). That schema doesn't preserve all the objects from the OSM database, but only those requested to build the tables for the requested tags.
Contrary to the original way of storing OSM objects, with this kind of extraction you will lose the relationships between objects (for example in OSM the same node can be used, let's say, as part of the relationship describing an administrative boundary and as part of a road; here you will get a road line in ln_road and a polygon in pg_boundary but you will loose the information that they were maybe partially sharing nodes). Notably due to this last point, the weight of the OSM extractions can be relatively high compared to the original file.
So I guess that this kind of scheme (which is one amongst other existing ways to transform OSM data) offers an interesting abstraction for those who are not accustomed to the OSM schema which use Node, Way and Relation elements (eg, in OSM, buildings can be represented as closed way or as relation, here you get "simply" polygons for these various buildings).