How To Map Cities With Vue, GeoJSON, And Google: Part 3

Daniel Smith
Apr 17 · 4 min read

Let’s use GeoJSON to show City Boundaries

We’re writing a Vue.js app that illustrates two ways to find an address: by searching from a location input, or by directly clicking on a map. From either input, we keep the marker and location input in sync.

Now we are going to pull in city boundaries that may be available for our current location on the map. We’ll call an API at nominatim.openstreetmap.org to get GeoJSON data, and feed that to a Google Maps Data Layer

In Part 4, we will do searches of Google Places. It will become apparent that some search results fall outside of city boundaries. In the final part, we will learn how to filter those out.

This is part 3 of 5.

The repository for this project is at https://github.com/DanielSmith/citymap

In this section:

  • get city & state
  • hook up getGeoJSON() — call for GeoJSON data
  • wrap data from nominatim.openstreetmap.org as a FeatureCollection
  • create data layer, and call the Google Maps API data method: addGeoJson() with our data

Get City & State

Our location is update by either a search, or a map click. If we are updating from a Map click, we’re going to make this call in App.vue:

this.cityState = this.getCityState(payload);

And that is going to get into figuring out our City and State. Google spreads the data out in a few fields. Because I am trying to work through a quick example, I opted to parse from a formatted address:

If you are wondering why I broke out cityStateHelper() as its own method, it is because there is a second place where it gets called. When we do a search in the location text field, we hit this code:

Note that this.theLocation is our v-model for handling the location text field.

Call for GeoJSON Data

At long last, we’re ready to reach out and get GeoJSON data to draw our city boundaries. Install the axios package from npm, so that we can make API requests:

npm install axios --save

And add to our imports in App.vue:

import axios from 'axios';

We call an API endpoint at http://nominatim.openstreetmap.org/

Although it returns GeoJSON data for most cities, there are two problems we will need to work around:

  • in this part, we will wrap the data we get with some additional GeoJSON, so that the Google Maps API addGeoJson() can properly use it.
  • in a later part, I will show how we can look through the various portions of data returned from nominatim, so that we can more reliably find the City Boundaries (for now, we blindly assume that City data is always in the first element, but that’s not always the case)

(note: The repository for this project is at https://github.com/DanielSmith/citymap — I do not show every single bit of code in this article)

In App.vue, the interesting bit is getCityData(theCity) We pass in a string such as “Austin,TX”. It is called from the getGeoJSON() click handler:

Over in Map.vue, the event is received in our updated mount() method:

This calls our new renderCityMap() method:

So, does it work?

We can start by clicking somewhere in NYC, and pressing the “Get City” button:

NYC with GeoJSON City Boundaries

There are some more interesting cases, with multiple polygons (some with holes in them). Austin, TX is one:

Chicago is good one:

There are cases where the wrong data comes back, such as San Mateo, CA:

Whoops. this is the county

That’s not the wrong data, per se. It’s just that in some instances, the County data is in the first element, instead of the City. We will address this in a later part.

Daniel Smith

Written by

codes/writes, LAMP / MEVN / MERN, loves film, music, and bantering - I am available for projects — javajoint [at the domain of] gmail [which is a dot] com

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade