Jersey City Zoning in 3D

Thanks to the latest by Mapbox I was able to add 3D buildings to my Jersey City Zoning Map. The buildings rendered below come from my shapefile of Jersey City buildings, which you can download from the city's open data portal, as opposed to OpenStreetMap. My data has more attributes (including zoning and assessment information) from when I merged buildings and parcel data. While the footprints are all the same as those in OSM (I first prepared that dataset specifically for OSM), you should use my dataset if you're interested in building ages, sale information, and zoning information. 

I created the building heights property from the "zoning description" field in the parcel dataset using an admittedly flawed method. The number of stories is usually listed first in a string of codes, followed by an "S". I used a regular expression to extract the number of stories and then I created a "bldgHeight" property (in meters) by multiplying the number of stories per building by 3. Lots of buildings are multi-level (e.g., a building might be one story across the entire lot but have two-stories on a portion of the lot). I grabbed the maximum number of stories in these cases. Some buildings are missing parcel information and so I don't know the number of stories. Some buildings that do merge with parcel information are missing the "zoning description" field. Unfortunately, all I could do for buildings with missing data is pipe in a "3" for one-story. 

I then did a few passes of clean-up based on personal knowledge. I flew around my map and corrected a few dozen buildings I know of that otherwise would have been a "3". For example, the buildings around Journal Square Station and Grove Station, the local high schools, and a few spots downtown. In some of these cases I was able to add additional layers to create the appearance of a 3D rendering (as opposed to just an extrusion). The Goldman Sacks Tower (the tallest building in view, below) is an example of this. All of the buildings have a "bldgHeight" of at least 3 (see my example code below for how I use this field), and all buildings have a minHeight of 0 (this field can be used to create the appearance of raised structures, like bridges) with one exception - the house I grew up in. Good luck trying to find it!

Right now, I've added different layers for each zone category by repeating code blocks. A much more elegant way of doing this would simply be to pass a different "filter" and "fill-color" property to the add.Layer function, but this works for now. I also added a link to a Google form so that anyone can submit updates to the building information. I'd like to make the map overlay collapsable at some point (it's a bit clunky right now). Finally, under advisement from Brian Platt in the Office of Innovation, I'm going to add a toggleable layer for recent development (2013+). That one might take a few more weeks to realize. Enjoy for now!

Go to the map. Go to the code.

    function loadBuildings() {
        map.addSource('Special', {
            type: 'vector',
            url: 'mapbox://sarahmlevine.sarahmlevine.1rz41on6'
            'id': 'Residential',
            'source': 'composite',
            'filter': ['==', 'zone', ('R-1' || 'R-1A' || 'R-1F' || 'R-2' || 'R-3' || 
                                      'R-4' || 'OR' || 'Caven Point')],
            'source-layer': 'buildings-1909vz',
            'type': 'fill',
            'minzoom': 14,
            'paint': {
                'fill-color': '#42e5f4',
                'fill-extrude-height': {
                    'type': 'identity',
                    'property': 'bldgHeight'
                'fill-extrude-base': {
                    'type': 'identity',
                    'property': 'minHeight'
                'fill-opacity': .5
  map.on('load', function() {