Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add choropleth support #40

Merged
merged 20 commits into from
Mar 29, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d3fcd8e
Add basic chloropleth support
Feb 3, 2018
d5a5435
Center zoom on click coordinates; rename polygons layer to 'cholorple…
Feb 19, 2018
07bf5e5
Add line_color, line_stroke, and line_width properties to Chloropleth…
Feb 20, 2018
3a5b3e6
Add chloropleth label layer; add template block for styling legend keys
Feb 20, 2018
bfd6a04
Add line styling to example chloropleth notebook
Feb 27, 2018
6b47dbc
Merge branch 'master' into chloropleth-support
Feb 27, 2018
79fd36a
Update internal documentation in ChloroplethViz class; add chloroplet…
Feb 27, 2018
360ef08
Update spelling to mapbox standard: 'choropleth'
Feb 28, 2018
ac8c100
Add tests for ChoroplethViz (currently uses polygons.geojson)
Feb 28, 2018
f1bcd21
Formatting and headers on choropleth notebook
Mar 2, 2018
9fa3853
Add vector layer support options; requesting direction for reconcilin…
Mar 6, 2018
b11c006
Single ChoroplethViz class defines either vector-based or geojson-bas…
Mar 17, 2018
722d747
Add support for categorical data-driven styling with vector data-join…
Mar 23, 2018
cb9972b
Merge branch 'master' into chloropleth-support; update styleUrl to st…
Mar 23, 2018
07b2ca7
Attempt to add test for utils.rgb_tuple_from_str
Mar 23, 2018
8084c7c
Merge branch 'master' into chloropleth-support
ryanbaumann Mar 27, 2018
cc147a0
Additional test coverage for ChoroplethViz and color_map, rgb_tuple_f…
Mar 29, 2018
29a3c36
Per @ryanbaumann 's comments: revert color data-join style to the old…
Mar 29, 2018
6af2548
Test fix
Mar 29, 2018
d80e99e
Minor refactor to color_map to prioritize returning exact match color…
Mar 29, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions docs-markdown/utils.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,50 @@ df = pd.read_csv(data_url)
color_breaks = [0,10,100,1000,10000]
color_stops = create_color_stops(color_breaks, colors='YlOrRd')
```

## rgb_tuple_from_str
Convert color represented as a string in format 'rgb(RRR,GGG,BBB)', 'rgba(RRR,GGG,BBB,alpha)', '#RRGGBB' or limited English color name (eg 'red') to tuple of integers from 0 to 255, (RRR, GGG, BBB).

### Params
**rgb_tuple_from_str**(_rgb_string_)

Parameter | Description
--|--
rgb_string | color represented as string in form 'rgb(RRR,GGG,BBB)', 'rgba(RRR,GGG,BBB,alpha)', '#RRGGBB', or limited HTML color names (eg 'red')

### Usage
```python
from mapboxgl.utils import rgb_tuple_from_str

# convert color string to tuple of integers
rgb_tuple_from_str('rgb(255,143,17')
```

## color_map
Convert color represented as a string in format 'rgb(RRR,GGG,BBB)' to tuple of integers from 0 to 255, (RRR, GGG, BBB).

### Params
**color_map**(_lookup, color_stops, default_color='rgb(122,122,122)'_)

Parameter | Description
--|--
lookup | value is numeric for interpolated colors or string for categorical color stops
color_stops | color ramp stops generated from `create_color_stops`, or custom list of numeric or categorical stops with paired colors
default_color | representation of color as hex, RGB, or RGBA strings

### Usage
```python
from mapboxgl.utils import create_color_stops, color_map

# interpolate color for numeric color_stops
color_stops = create_color_stops([0, 50, 100, 500, 1500], colors='YlOrRd')
color = color_map(73, color_stops)

# categorical look up
match_color_stops = [
['Massachusetts', 'rgb(46,204,113)'],
['Utah', 'rgb(231,76,60)'],
['California', 'rgb(142,68,173)'],
]
color = color_map('California', match_color_stops, default_color='grey)')
```
32 changes: 13 additions & 19 deletions docs-markdown/viz.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,21 +284,25 @@ viz.show()

## class ChoroplethViz

The `ChoroplethViz` object handles the creation of a choropleth map and inherits from the `MapViz` class. It applies a thematic map style to polygon features with color shading in proportion to the intensity of the data being displayed.
The `ChoroplethViz` object handles the creation of a choropleth map and inherits from the `MapViz` class. It applies a thematic map style to polygon features with color shading in proportion to the intensity of the data being displayed. Choropleth polygons can be initialized with geojson source or vector source styled using the data-join technique.

### Params
**ChoroplethViz**(_data, label_property=None, color_property=None, color_stops=None, color_default='grey', color_function_type='interpolate', line_color='white', line_stroke='solid', line_width=1, *args, **kwargs_)
**ChoroplethViz**(_data, vector_url=None, vector_layer_name=None, vector_join_property=None, data_join_property=None, # vector only label_property=None, color_property=None, color_stops=None, color_default='grey', color_function_type='interpolate', line_color='white', line_stroke='solid', line_width=1, *args, **kwargs_)

Parameter | Description | Example
--|--|--
data | GeoJson file name or object
data | can be either GeoJSON (containing polygon features) or JSON for data-join technique with vector polygons |
vector_url | optional property to define vector polygon source | "mapbox://mapbox.us_census_states_2015"
vector_layer_name | property to define target layer of vector source if using vector polygon source | "states"
vector_join_property | property to aid in determining color for styling vector polygons | "STATEFP"
data_join_property | property of json data to use as link to vector features | "state_name"
label_property | property to use for marker label | "density"
color_property | property to determine fill color | "density"
color_stops | property to determine fill color | [[0, "red"], [0.5, "blue"], [1, "green"]]
color_default | property to determine default fill color in match lookups | "#F0F0F0"
color_function_type | property to determine type of expression used by Mapbox to assign color | "interpolate"
line_color | property to determine choropleth border line color | "#FFFFFF"
line_stroke | property to determine choropleth border line stroke (one of solid, dashed, dotted, dash dot) | "solid"
line_stroke | property to determine choropleth border line stroke (one of solid (-), dashed (--), dotted (:), dash dot (-.)) | "solid" or "-"
line_width | property to determine choropleth border line width | 1

[View options](https://github.com/mapbox/mapboxgl-jupyter/blob/master/docs-markdown/viz.md#params)
Expand All @@ -307,33 +311,23 @@ line_width | property to determine choropleth border line width | 1
```python
import os
from mapboxgl.viz import *
from mapboxgl.utils import *

# Must be a public token, starting with `pk`
token = os.getenv('MAPBOX_ACCESS_TOKEN')

# Color stops
color_stops = [
[0.0, 'rgb(255,255,204)'],
[50.0, 'rgb(255,237,160)'],
[100.0, 'rgb(253,141,60)'],
[500.0, 'rgb(227,26,28)'],
[2500.0, 'rgb(189,0,38)'],
[5000.0, 'rgb(128,0,38)']
]

# Create Choropleth
# Create Choropleth with GeoJSON Source
viz = ChoroplethViz('us-states.geojson',
access_token=token,
color_property='density',
color_stops=color_stops,
color_stops=create_color_stops([0, 50, 100, 500, 1500], colors='YlOrRd'),
color_function_type='interpolate',
line_stroke='dashed',
line_stroke='--',
line_color='rgb(128,0,38)',
line_width=1,
opacity=0.8,
center=(-96, 37.8),
zoom=3,
below_layer='waterway-label
below_layer='waterway-label'
)
viz.show()
```
Expand Down
58 changes: 48 additions & 10 deletions examples/choropleth-viz-example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
},
"outputs": [],
"source": [
"# create choropleth from polygon features stored as GeoJSON\n",
"viz = ChoroplethViz('us-states.geojson', \n",
" color_property='density',\n",
" color_stops=create_color_stops([0, 50, 100, 500, 1500], colors='YlOrRd'),\n",
Expand Down Expand Up @@ -71,7 +72,7 @@
" ['Utah', 'rgb(231,76,60)'],\n",
" ['California', 'rgb(142,68,173)'],\n",
"]\n",
" \n",
"\n",
"viz = ChoroplethViz('us-states.geojson', \n",
" color_property='name', \n",
" color_stops = match_color_stops, \n",
Expand All @@ -89,7 +90,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Vector polygon source with data-join technique"
"## Vector polygon source with data-join technique\n",
"\n",
"In this configuration, properties in JSON data are used to calculate colors to style polygons from the vector source."
]
},
{
Expand All @@ -98,24 +101,59 @@
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from mapboxgl.viz import *\n",
"\n",
"# Must be a public token, starting with `pk`\n",
"token = os.getenv('MAPBOX_ACCESS_TOKEN')\n",
"\n",
"# must be json object (need to extend to use referenced json file)\n",
"# must be JSON object (need to extend to use referenced JSON file)\n",
"data = [{\"id\": \"01\", \"name\": \"Alabama\", \"density\": 94.65}, {\"id\": \"02\", \"name\": \"Alaska\", \"density\": 1.264}, {\"id\": \"04\", \"name\": \"Arizona\", \"density\": 57.05}, {\"id\": \"05\", \"name\": \"Arkansas\", \"density\": 56.43}, {\"id\": \"06\", \"name\": \"California\", \"density\": 241.7}, {\"id\": \"08\", \"name\": \"Colorado\", \"density\": 49.33}, {\"id\": \"09\", \"name\": \"Connecticut\", \"density\": 739.1}, {\"id\": \"10\", \"name\": \"Delaware\", \"density\": 464.3}, {\"id\": \"11\", \"name\": \"District of Columbia\", \"density\": 10065}, {\"id\": \"12\", \"name\": \"Florida\", \"density\": 353.4}, {\"id\": \"13\", \"name\": \"Georgia\", \"density\": 169.5}, {\"id\": \"15\", \"name\": \"Hawaii\", \"density\": 214.1}, {\"id\": \"16\", \"name\": \"Idaho\", \"density\": 19.15}, {\"id\": \"17\", \"name\": \"Illinois\", \"density\": 231.5}, {\"id\": \"18\", \"name\": \"Indiana\", \"density\": 181.7}, {\"id\": \"19\", \"name\": \"Iowa\", \"density\": 54.81}, {\"id\": \"20\", \"name\": \"Kansas\", \"density\": 35.09}, {\"id\": \"21\", \"name\": \"Kentucky\", \"density\": 110}, {\"id\": \"22\", \"name\": \"Louisiana\", \"density\": 105}, {\"id\": \"23\", \"name\": \"Maine\", \"density\": 43.04}, {\"id\": \"24\", \"name\": \"Maryland\", \"density\": 596.3}, {\"id\": \"25\", \"name\": \"Massachusetts\", \"density\": 840.2}, {\"id\": \"26\", \"name\": \"Michigan\", \"density\": 173.9}, {\"id\": \"27\", \"name\": \"Minnesota\", \"density\": 67.14}, {\"id\": \"28\", \"name\": \"Mississippi\", \"density\": 63.5}, {\"id\": \"29\", \"name\": \"Missouri\", \"density\": 87.26}, {\"id\": \"30\", \"name\": \"Montana\", \"density\": 6.858}, {\"id\": \"31\", \"name\": \"Nebraska\", \"density\": 23.97}, {\"id\": \"32\", \"name\": \"Nevada\", \"density\": 24.8}, {\"id\": \"33\", \"name\": \"New Hampshire\", \"density\": 147}, {\"id\": \"34\", \"name\": \"New Jersey\", \"density\": 1189}, {\"id\": \"35\", \"name\": \"New Mexico\", \"density\": 17.16}, {\"id\": \"36\", \"name\": \"New York\", \"density\": 412.3}, {\"id\": \"37\", \"name\": \"North Carolina\", \"density\": 198.2}, {\"id\": \"38\", \"name\": \"North Dakota\", \"density\": 9.916}, {\"id\": \"39\", \"name\": \"Ohio\", \"density\": 281.9}, {\"id\": \"40\", \"name\": \"Oklahoma\", \"density\": 55.22}, {\"id\": \"41\", \"name\": \"Oregon\", \"density\": 40.33}, {\"id\": \"42\", \"name\": \"Pennsylvania\", \"density\": 284.3}, {\"id\": \"44\", \"name\": \"Rhode Island\", \"density\": 1006}, {\"id\": \"45\", \"name\": \"South Carolina\", \"density\": 155.4}, {\"id\": \"46\", \"name\": \"South Dakota\", \"density\": 98.07}, {\"id\": \"47\", \"name\": \"Tennessee\", \"density\": 88.08}, {\"id\": \"48\", \"name\": \"Texas\", \"density\": 98.07}, {\"id\": \"49\", \"name\": \"Utah\", \"density\": 34.3}, {\"id\": \"50\", \"name\": \"Vermont\", \"density\": 67.73}, {\"id\": \"51\", \"name\": \"Virginia\", \"density\": 204.5}, {\"id\": \"53\", \"name\": \"Washington\", \"density\": 102.6}, {\"id\": \"54\", \"name\": \"West Virginia\", \"density\": 77.06}, {\"id\": \"55\", \"name\": \"Wisconsin\", \"density\": 105.2}, {\"id\": \"56\", \"name\": \"Wyoming\", \"density\": 5.851}, {\"id\": \"72\", \"name\": \"Puerto Rico\", \"density\": 1082}]\n",
"\n",
"# create choropleth map with vector source styling use data in JSON object\n",
"viz = ChoroplethViz(data, \n",
" vector_url='mapbox://mapbox.us_census_states_2015',\n",
" vector_layer_name='states',\n",
" vector_join_color_property='STATEFP',\n",
" vector_join_property='STATEFP',\n",
" data_join_property='id',\n",
" color_property='density',\n",
" color_stops=create_color_stops([0, 50, 100, 500, 1500], colors='YlOrRd'),\n",
" line_stroke='dashed',\n",
" line_color='rgb(128,0,38)',\n",
" opacity=0.8,\n",
" center=(-96, 37.8),\n",
" zoom=3,\n",
" below_layer='waterway-label'\n",
" )\n",
"viz.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Vector polygon source with data-join technique, categorical color scheme"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# must be JSON object (need to extend to use referenced JSON file)\n",
"data = [{\"id\": \"01\", \"name\": \"Alabama\", \"density\": 94.65}, {\"id\": \"02\", \"name\": \"Alaska\", \"density\": 1.264}, {\"id\": \"04\", \"name\": \"Arizona\", \"density\": 57.05}, {\"id\": \"05\", \"name\": \"Arkansas\", \"density\": 56.43}, {\"id\": \"06\", \"name\": \"California\", \"density\": 241.7}, {\"id\": \"08\", \"name\": \"Colorado\", \"density\": 49.33}, {\"id\": \"09\", \"name\": \"Connecticut\", \"density\": 739.1}, {\"id\": \"10\", \"name\": \"Delaware\", \"density\": 464.3}, {\"id\": \"11\", \"name\": \"District of Columbia\", \"density\": 10065}, {\"id\": \"12\", \"name\": \"Florida\", \"density\": 353.4}, {\"id\": \"13\", \"name\": \"Georgia\", \"density\": 169.5}, {\"id\": \"15\", \"name\": \"Hawaii\", \"density\": 214.1}, {\"id\": \"16\", \"name\": \"Idaho\", \"density\": 19.15}, {\"id\": \"17\", \"name\": \"Illinois\", \"density\": 231.5}, {\"id\": \"18\", \"name\": \"Indiana\", \"density\": 181.7}, {\"id\": \"19\", \"name\": \"Iowa\", \"density\": 54.81}, {\"id\": \"20\", \"name\": \"Kansas\", \"density\": 35.09}, {\"id\": \"21\", \"name\": \"Kentucky\", \"density\": 110}, {\"id\": \"22\", \"name\": \"Louisiana\", \"density\": 105}, {\"id\": \"23\", \"name\": \"Maine\", \"density\": 43.04}, {\"id\": \"24\", \"name\": \"Maryland\", \"density\": 596.3}, {\"id\": \"25\", \"name\": \"Massachusetts\", \"density\": 840.2}, {\"id\": \"26\", \"name\": \"Michigan\", \"density\": 173.9}, {\"id\": \"27\", \"name\": \"Minnesota\", \"density\": 67.14}, {\"id\": \"28\", \"name\": \"Mississippi\", \"density\": 63.5}, {\"id\": \"29\", \"name\": \"Missouri\", \"density\": 87.26}, {\"id\": \"30\", \"name\": \"Montana\", \"density\": 6.858}, {\"id\": \"31\", \"name\": \"Nebraska\", \"density\": 23.97}, {\"id\": \"32\", \"name\": \"Nevada\", \"density\": 24.8}, {\"id\": \"33\", \"name\": \"New Hampshire\", \"density\": 147}, {\"id\": \"34\", \"name\": \"New Jersey\", \"density\": 1189}, {\"id\": \"35\", \"name\": \"New Mexico\", \"density\": 17.16}, {\"id\": \"36\", \"name\": \"New York\", \"density\": 412.3}, {\"id\": \"37\", \"name\": \"North Carolina\", \"density\": 198.2}, {\"id\": \"38\", \"name\": \"North Dakota\", \"density\": 9.916}, {\"id\": \"39\", \"name\": \"Ohio\", \"density\": 281.9}, {\"id\": \"40\", \"name\": \"Oklahoma\", \"density\": 55.22}, {\"id\": \"41\", \"name\": \"Oregon\", \"density\": 40.33}, {\"id\": \"42\", \"name\": \"Pennsylvania\", \"density\": 284.3}, {\"id\": \"44\", \"name\": \"Rhode Island\", \"density\": 1006}, {\"id\": \"45\", \"name\": \"South Carolina\", \"density\": 155.4}, {\"id\": \"46\", \"name\": \"South Dakota\", \"density\": 98.07}, {\"id\": \"47\", \"name\": \"Tennessee\", \"density\": 88.08}, {\"id\": \"48\", \"name\": \"Texas\", \"density\": 98.07}, {\"id\": \"49\", \"name\": \"Utah\", \"density\": 34.3}, {\"id\": \"50\", \"name\": \"Vermont\", \"density\": 67.73}, {\"id\": \"51\", \"name\": \"Virginia\", \"density\": 204.5}, {\"id\": \"53\", \"name\": \"Washington\", \"density\": 102.6}, {\"id\": \"54\", \"name\": \"West Virginia\", \"density\": 77.06}, {\"id\": \"55\", \"name\": \"Wisconsin\", \"density\": 105.2}, {\"id\": \"56\", \"name\": \"Wyoming\", \"density\": 5.851}, {\"id\": \"72\", \"name\": \"Puerto Rico\", \"density\": 1082}]\n",
"\n",
"match_color_stops = [\n",
" ['Massachusetts', 'rgb(46,204,113)'],\n",
" ['Utah', 'rgb(231,76,60)'],\n",
" ['California', 'rgb(142,68,173)'],\n",
"]\n",
"\n",
"# create choropleth map with vector source styling use data in JSON object\n",
"viz = ChoroplethViz(data, \n",
" vector_url='mapbox://mapbox.us_census_states_2015',\n",
" vector_layer_name='states',\n",
" vector_join_property='STATEFP',\n",
" data_join_property='id',\n",
" color_property='name',\n",
" color_stops=match_color_stops,\n",
" color_default = 'rgba(52,73,94,0.5)', \n",
" opacity=0.8,\n",
" center=(-96, 37.8),\n",
" zoom=3,\n",
" below_layer='waterway-label'\n",
Expand Down
18 changes: 18 additions & 0 deletions mapboxgl/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,3 +337,21 @@
12: ['rgb(141,211,199)', 'rgb(255,255,179)', 'rgb(190,186,218)', 'rgb(251,128,114)', 'rgb(128,177,211)', 'rgb(253,180,98)', 'rgb(179,222,105)', 'rgb(252,205,229)', 'rgb(217,217,217)', 'rgb(188,128,189)', 'rgb(204,235,197)', 'rgb(255,237,111)']
}
)

# a few HTML / X11 color names
common_html_colors = {
'red': 'rgb(255,0,0)',
'orange': 'rgb(255,165,0)',
'yellow': 'rgb(255,255,0)',
'green': 'rgb(0,128,0)',
'blue': 'rgb(0,0,255)',
'purple': 'rgb(128,0,128)',
'pink': 'rgb(255,192,203)',
'white': 'rgb(255,255,255)',
'grey': 'rgb(128,128,128)',
'gray': 'rgb(128,128,128)',
'black': 'rgb(0,0,0)',
'brown': 'rgb(139,69,19)',
'magenta': 'rgb(255,0,255)',
'cyan': 'rgb(0,255,255)',
}
11 changes: 8 additions & 3 deletions mapboxgl/templates/choropleth.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

<!-- update legend item key style -->
{% block extra_css %}
<style type='text/css'>
.legend div span { border-radius: 20%; }
</style>
<style type='text/css'>
.legend div span { border-radius: 20%; }
</style>
{% endblock extra_css %}

{% block javascript %}
Expand Down Expand Up @@ -103,6 +103,8 @@
closeOnClick: false
});

{% block choropleth_popup %}

// Show the popup on mouseover
map.on('mousemove', 'choropleth-fill', function(e) {
map.getCanvas().style.cursor = 'pointer';
Expand All @@ -120,6 +122,8 @@
.addTo(map);
});

{% endblock choropleth_popup %}

map.on('mouseleave', 'choropleth-fill', function() {
map.getCanvas().style.cursor = '';
popup.remove();
Expand All @@ -134,4 +138,5 @@
});

});

{% endblock %}
45 changes: 20 additions & 25 deletions mapboxgl/templates/vector_choropleth.html
Original file line number Diff line number Diff line change
@@ -1,26 +1,6 @@
{% extends "choropleth.html" %}

{% block choropleth %}

var joinData = {{ joinData }};

{% if joinData %}
var vectorColorStops = [],
popUpKeys = [];

// create categorical color stops for features in vector layer
joinData.forEach(function(row, index) {
var red = Math.max(255 - row["{{ colorProperty }}"], 0),
green = Math.max(255 - row["{{ colorProperty }}"], 0),
blue = Math.min(204 + row["{{ colorProperty }}"], 255);

var color = "rgba(" + red + ", " + green + ", " + blue + ", 1)";
vectorColorStops.push([row["id"], color]);

// for adding joined data to pop-up
popUpKeys[row["{{ dataJoinProperty }}"]] = row["{{ colorProperty }}"];
});
{% endif %}
{% block choropleth %}

// Add vector data source
map.addSource("vector-data", {
Expand All @@ -35,7 +15,7 @@
"source": "vector-data",
"source-layer": "{{ vectorLayer }}",
"paint": {
"fill-color": generatePropertyExpression("match", "{{ vectorJoinColorProperty }}", vectorColorStops, "{{ defaultColor }}"),
"fill-color": generatePropertyExpression("match", "{{ vectorJoinColorProperty }}", {{ vectorColorStops }}, "{{ defaultColor }}"),
"fill-opacity": {{ opacity }}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add layer filter here (see comment on how to create)

}, "{{ belowLayer }}");
Expand Down Expand Up @@ -79,9 +59,23 @@
}
}, "{{belowLayer}}" );

{% endblock choropleth %}
{% endblock choropleth %}

{% block choropleth_popup %}

// extract JSON property used for data-driven styling to add to popup
Copy link
Contributor

@ryanbaumann ryanbaumann Mar 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this section to create the popup join data before the layer creation in the map.on(style.load) function. We'll want to generate a filter expression here too that limits the vector features visible to ones that match data in the user's data.

Also, I changed the syntax for the color data-join style back to the old mapboxgl property functions in the code below. It's faster than the new expression syntax for this use case and won't be completely deprecated for a while yet, so I switched the example below to use that syntax.

Here's how I'd recommend doing it:

{% block choropleth %}
    
    // extract JSON property used for data-driven styling to add to popup
    {% if joinData %}

        let joinData = {{ joinData }};
        # Create filter for layers from join data
        let layerFilter = ['in', "{{ vectorJoinColorProperty }}"]
        var popUpKeys = {};

        joinData.forEach(function(row, index) {
            popUpKeys[row["{{ dataJoinProperty }}"]] = row["{{ colorProperty }}"];
            layerFilter.push(row["{{ dataJoinProperty }}"])
        });

    {% endif %}

    // Add vector data source
    map.addSource("vector-data", {
        type: "vector",
        url: "{{ vectorUrl }}",
    });

    // Add layer from the vector tile source with data-driven style
    map.addLayer({
        "id": "choropleth-fill",
        "type": "fill",
        "source": "vector-data",
        "source-layer": "{{ vectorLayer }}",
        "paint": {
            "fill-color": {
                "type": "categorical",
                "property": "{{ vectorJoinColorProperty }}", 
                "stops": {{ vectorColorStops }}, 
                "default": "{{ defaultColor }}"
            },
            "fill-opacity": {{ opacity }}
        },
        filter: layerFilter
    }, "{{ belowLayer }}");

    // Add border layer
    map.addLayer({
        "id": "choropleth-line",
        "source": "vector-data",
        "source-layer": "{{ vectorLayer }}",
        "type": "line",
        "layout": {
            "line-join": "round",
            "line-cap": "round"
        },
        "paint": {
            {% if lineDashArray %}
                "line-dasharray": {{ lineDashArray }},
            {% endif %}
            "line-color": "{{ lineColor }}",
            "line-width": {{ lineWidth }},
            "line-opacity": {{ opacity }}
        },
        filter: layerFilter
    }, "{{ belowLayer }}" );

    // Add label layer
    map.addLayer({
        "id": "choropleth-label",
        "source": "vector-data",
        "source-layer": "{{ vectorLayer }}",
        "type": "symbol",
        "layout": {
            {% if labelProperty %}
            "text-field": "{{ labelProperty }}",
            {% endif %}
            "text-size" : generateInterpolateExpression('zoom', [[0,8],[22,16]] ),
            "text-offset": [0,-1]
        },
        "paint": {
            "text-halo-color": "white",
            "text-halo-width": 1
        },
        filter: layerFilter
    }, "{{belowLayer}}" );

{% endblock choropleth %}

{% if joinData %}

let joinData = {{ joinData }};

var popUpKeys = {};

joinData.forEach(function(row, index) {
popUpKeys[row["{{ dataJoinProperty }}"]] = row["{{ colorProperty }}"];
});

{% endif %}

{% block choropleth_popup %}
// Show the popup on mouseover
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add in the logic to remove the popup here on mouseleave.

    map.on('mouseleave', 'choropleth-fill', function() {
        map.getCanvas().style.cursor = '';
        popup.remove();
    });
    
    // Fly to on click
    map.on('click', 'choropleth-fill', function(e) {
        map.flyTo({
            center: e.lngLat,
            zoom: map.getZoom() + 1
        });
    });

map.on('mousemove', 'choropleth-fill', function(e) {
map.getCanvas().style.cursor = 'pointer';
Expand All @@ -101,4 +95,5 @@
.setHTML(popup_html)
.addTo(map);
});
{% endblock choropleth_popup %}

{% endblock choropleth_popup %}
Loading