3
votes

I'm trying to style my mapbox layer so that all the states in the US are different shades of blue and all the provinces in Canada are different shades of red. I'm trying to follow this tutorial found at https://docs.mapbox.com/mapbox-gl-js/example/data-join/ but I haven't gotten it to work with my code yet. Can you see what I might be doing wrong?

My type and source is of geoJSON. My first approach has been to color the states first then once I have that figured out I was hoping to do the same to the provinces. The example uses vector tiles so maybe that's a reason why my code isn't working right now. My map shows up fine (all states and provinces are outlined and shaded with the same color using geoJSON)without the added code from the tutorial besides all the states and provinces are the same color obviously.. but once I try to implement the examples code all styling goes away and I am left with just a plain map and nothing outlined at all.

My code while trying to implement the examples code looks like this

mapboxgl.accessToken = 'pk.eyJ1IjoicmNvY29ubm9yIiwiYSI6ImNrMDVjZWhyZTA5aDQzaG4wc29ra2F3eHYifQ.icA8-NotLlzhryFxFLvVtQ';
//src="jquery-3.4.1.min.js"
var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v11',
    center: [-99.9, 41.5],
    zoom: 1
});

// Join local JSON data with vector tile geometry
// USA unemployment rate in 2009
// Source https://data.bls.gov/timeseries/LNS14000000
var maxValue = 13;
var data = [
    { "STATE" : "ME", "unemployment": 13.17 },
    { "STATE" :"MA", "unemployment": 9.5 },
    { "STATE" :"MI", "unemployment": 12.15 },
    { "STATE" :"MT", "unemployment": 8.99 },
    { "STATE" :"NV", "unemployment": 11.83 },
    { "STATE" :"NJ", "unemployment": 7.52 },
    { "STATE" :"NY", "unemployment": 6.44 },
    { "STATE" :"NC", "unemployment": 5.17 },
    { "STATE" :"OH", "unemployment": 9.67 },
    { "STATE" :"PN", "unemployment": 10.64 },
    { "STATE" :"RI", "unemployment": 12.38 },
    { "STATE" :"TN", "unemployment": 10.13 },
    { "STATE" :"TX", "unemployment": 9.58 },
    { "STATE" :"UT", "unemployment": 10.63 },
    { "STATE" :"WA", "unemployment": 8.09 },
    { "STATE" :"WI", "unemployment": 5.93 },
    { "STATE" :"PR", "unemployment": 9.86 },
    { "STATE" :"MD", "unemployment": 9.81 },
    { "STATE" :"AL", "unemployment": 7.82 },
    { "STATE" :"AK", "unemployment": 8.35 },
    { "STATE" :"AZ", "unemployment": 9.1 },
    { "STATE" :"AR", "unemployment": 10.69 },
    { "STATE" :"CA", "unemployment": 11.53 },
    { "STATE" :"CO", "unemployment": 9.29 },
    { "STATE" :"CT", "unemployment": 9.94 },
    { "STATE" :"DE", "unemployment": 9.29 },
    { "STATE" :"DC", "unemployment": 5.45 },
    { "STATE" :"FL", "unemployment": 4.21 },
    { "STATE" :"GA", "unemployment": 4.27 },
    { "STATE" :"HI", "unemployment": 4.09 },
    { "STATE" :"ID", "unemployment": 7.83 },
    { "STATE" :"IL", "unemployment": 8.01 },
    { "STATE" :"IN", "unemployment": 9.34 },
    { "STATE" :"IA", "unemployment": 11.23 },
    { "STATE" :"KS", "unemployment": 7.08 },
    { "STATE" :"KY", "unemployment": 11.22 },
    { "STATE" :"LA", "unemployment": 6.2 },
    { "STATE" :"MN", "unemployment": 9.11 },
    { "STATE" :"MS", "unemployment": 10.42 },
    { "STATE" :"MO", "unemployment": 8.89 },
    { "STATE" :"NE", "unemployment": 11.03 },
    { "STATE" :"NH", "unemployment": 7.35 },
    { "STATE" :"NM", "unemployment": 8.92 },
    { "STATE" :"ND", "unemployment": 7.65 },
    { "STATE" :"OK", "unemployment": 8.01 },
    { "STATE" :"OR", "unemployment": 7.62 },
    { "STATE" :"SC", "unemployment": 7.77 },
    { "STATE" :"SD", "unemployment": 8.49 },
    { "STATE" :"VT", "unemployment": 9.42 },
    { "STATE" :"WV", "unemployment": 8.01 },
    { "STATE" :"WY", "unemployment": 9.34 },
    { "STATE" :"VA", "unemployment": 7.59 }
];

map.on('load', function() {

    // Add source for state polygons hosted on Mapbox, based on US Census Data:
    // https://www.census.gov/geo/maps-data/data/cbf/cbf_state.html
    map.addSource("regions", {
        type: "geojson",
        data: {**super long geojson**}

    var expression = ["match", ["get", "STATE"]];

    // Calculate color for each state based on the unemployment rate
    data.forEach(function (row) {
        var green = (row["unemployment"] / maxValue) * 255;
        var color = "rgba(" + 0 + ", " + green + ", " + 0 + ", 1)";
        expression.push(row["STATE"], color);
    });

    // Last value is the default, used where there is no data
    expression.push("rgba(0,0,0,0)");

    map.addLayer({
        "id": "regions_layer",
        "type": "fill",
        "source": "regions",
        "paint": {
        "fill-color": expression,
        'fill-outline-color': 'black',
        "fill-opacity": 0.2
        },
        "filter": ["==", "$type", "Polygon"]
        }, 'waterway-lable');
});

The tags in my html look like this.. the commented out one are what I was using before trying to change the colors

<!--<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.3.0/mapbox-gl.js'></script>-->
    <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.3.1/mapbox-gl.js'></script>
    <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.3.1/mapbox-gl.css' rel='stylesheet' />
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
    <!--<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.3.0/mapbox-gl.css' rel='stylesheet' />-->

My geojson file is super long but Ill give a snippet of it to help get a better idea of the data.

{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[A BUNCH OF CORDINATES I DONT THINK RELATES TO THE PROBLEM[-57.10424,51.41267]]]]},"properties":{"name":"Quebec","cartodb_id":1,"created_at":"2014-10-16T13:22:00Z","updated_at":"2014-10-16T13:22:00Z","GEO_ID":"0400000CA01","STATE":"QC","NAME":"Quebec","COUNTRY":"CA","CENSUSAREA":""}},{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[A BUNCH MORE CORDINATES

End result I am trying to shade all different states in my regions_layer a different shade of blue and all of my provinces a different shade of red. I can go into the paint properties and make the whole layer have a certain shade but can't get individual states to have a certain shade.

The geoJSON above is one of my canada provinces but us one would have a "STATE": IN, "NAME" "Indiana".. for example.

Can you see anything I'm doing wrong?? Thanks

1

1 Answers

1
votes

You can use mapbox's own layers and style expressions.

  1. Find the layers. For states, it is state-label.
  2. Build a style expression.
  3. Update paint properties using map.setPaintProperty(). Here, we will update text-color since we're trying to style a text layer.
// Get default property value
const defaultProp = map.getPaintProperty("state-label", "text-color");

// Simplified input
const states = [
  { state: "Montana", color: "red" },
  { state: "Iowa", color: "green" },
  { state: "Utah", color: "blue" }
];

// Build a switch-case style expression
const exprs = ["case"];
states.forEach(state => {
  exprs.push(["==", ["get", "name"], state.state]);
  exprs.push(state.color);
})
exprs.push(defaultProp);

// Update paint properties
map.setPaintProperty("state-label", "text-color", exprs);

Here's a working codepen: https://codepen.io/manishraj/full/rNBdbwg

More on expressions: https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions