Create an interactive community map in Drupal 7 with Leaflet

 

In this tutorial, I'll show you how to create a clickable community map where each community represents a Drupal node.

I admit, I don't know a lot about mapping apart from being fairly adept at reading them. I've implemented some basic interactive maps, not much beyond showing locations and certainly nothing that was integrated with Drupal's node/entity system. 

That is why Amber Matz (@amberhimes on Twitter) and Acquia deserve a ton of credit for helping me along with their excellent webcast, Easily Create Maps in Drupal with Leaflet. If you have no experience with the Leaflet or Geofield modules, you'll need to run through this tutorial, first. It will get you familiar with these tools as well as how to use them with Views to show multiple nodes on a map.  

Now, we're essentially going to do the same thing, except using a different kind of data to display a different type of map. Instead of latitude/longitude, we'll be using GeoJSON. Instead of points on a map, we'll be showing areas. OK, that's not really the same at all. But the set-up really is very similar, as you will see.

You should already have the following modules enabled: Views, Geofield, and Leaflet, as well as their dependencies Chaos Tools, Libraries, and geoPHP

Now about that GeoJSON stuff. GeoJSON is a JSON-based standard for encoding geographic data structures for the web. With GeoJSON we can define (in addition to other things) areas with path outlines, such as a provincial border or community boundary. But what about the data itself? Where does it come from and how do I get it? This stumped me, at first. I had no idea how to get my hands on the plotted data for all neighbourhoods in Edmonton, Alberta (my awesome hometown). As it happened, this was a process of discovery that began with "Whew, I'm lucky to find this", culminating in a "Really, I can do that?" wow-moment at the end of the day.

I was definitely lucky to find Click That Hood, an open source project by nonprofit Code for America. What this project has (besides a game app that is surprisingly addictive) is GeoJSON data for dozens of cities across 11 countries. Go to their GitHub page, navigate to folder public/data, and scroll down the list of .geojson files. Click on the file, then click "Raw" to get at the data. This data is what I used to get my initial results.

What I later discovered, however, is that I can also generate my own GeoJSON file with the help of the City of Edmonton Neighbourhood Boundaries map (your town might have one, too) and Ogre, an online app that converts other formats to and from GeoJSON. What I'm looking to download from my source (in this case, the City of Edmonton) is an ESRI Shapefile export, which is actually a zipped collection of files. The entire zipped file is uploaded to Ogre, and voila: GeoJSON. That's pretty sweet.

Now that you've got your data in hand, let's get started.

Create a content type

  1. Create a new content type called "Community"

  2. Add a field:

    Name
    "Area"
    Field type
    Geofield
    Widget
    GeoJSON
    Number of values
    1
  3. Click the Manage Display tab. Here you have sub-options for Default and Teaser. Under Default, the settings for the Area field are: 

    Format
    Leaflet

    Click the gear icon. Settings:

    Leaflet map
    OSM Mapnik

    For your Teaser, the settings for Area are:

    Format
    <Hidden>

Add communities

  1. Create new content by going to Content > Add content > Community

  2. Put the community name in the title (e.g. "Downtown" or "Riverside").

  3. Now paste your GeoJSON object into the Area field. You can either copy your large .geojson file containing all of the communities and then strip out all other communities except the one you need (messy), or you can copy the one line of data pertaining to your community (called a type member) and paste it into this wrapper: 

    {
      "type": "FeatureCollection",
      "features": [ 
        .. paste your community data here (remove the comma at the end of the line!) 
      ]
    }
     

    Filled in and formatted, it would look something like this:

    {
      "type": "FeatureCollection",
      "features": [ 
        { 
          "type": "Feature", 
          "id": 102, 
          "properties": {
            "name": "Downtown", 
            "cartodb_id": 103, 
            "created_at": "2013-11-27T23:29:57+0100", 
            "updated_at": "2013-11-27T23:29:57+0100" 
          }, 
          "geometry": { 
            "type": "Polygon", 
            "coordinates": [ 
              [ 
                [ -113.509835, 53.540325 ], 
                [ -113.509835, 53.54038 ], 
                [ -113.509842, 53.54038 ], 
                [ -113.509841, 53.540798 ], 
                [ -113.509839, 53.540938 ], 
                [ -113.510264, 53.540937 ], 
                [ .. etc. ]
              ] 
            ] 
          } 
        } 
      ]
    }
    

    It's worth noting that this textarea will only accept one object containing one member (e.g. community). Also, if your community data was previously part of a series, make sure to delete the comma at the end of the string.

  4. Now hit save. If you now view the node you should see your community plotted out on a map. 

  5. Repeat these steps for each community.

Next, we will create a map showing all of our communities. 

Create a view

  1. Create a new view. Settings:

    View name
    "Communities"
    Show
    Content
    of type
    Community
    Create a page
    checked
    Items to display
    0
    Use a pager
    unchecked
    Click Continue & Edit.
  2. Select Leaflet Map as the format. This will automatically add a field, Content: Title.

  3. Add a new field. Settings:

    Type
    Content: Area
    Create a label
    unchecked
    Exclude from display
    checked
    Apply changes.
  4. Now adjust Settings under Format:

    Data Source
    Content: Area
    Title field
    Content: Title
    Description Content
    <node entity>
    View mode
    Teaser
    Map height
    600 px
  5. Save the view.

View the results

Visit the view URL (probably /communities if you followed the instructions precisely) to view your community map!

See what mine looks like.  

Troubleshooting

System error when saving Community node: Area: Specified location data is invalid. Recheck your GeoJSON string. Did you include the wrapper? Is there a comma or bracket where there shouldn't be?

Some, but not all communities are displayed. In your view, is your pager set to display all items? 

Of course there are other ways of working with GeoJSON data in Drupal. Look at Views GeoJSON to generate your own GeoJSON-formatted files from Geofield data, or if you want to work with existing (possibly externally hosted) files, you may find what you need in the Feeds module. (I haven't attempted this, yet, but I'd love to hear from those who have.)

As always, great work from the Drupalers who build and help maintain these amazing tools! I never cease to be amazed. 

- Lara