How To Map Cities With Vue, GeoJSON, And Google: Part 3
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.
- Part 1: Set up Vue.js + Google Maps (move marker when clicked)
- Part 2: Location searching with autocomplete, or update location via mouse click
- Part 3: Get GeoJSON data from nominatim, and draw city boundaries on map
- Part 4: Search via Google Places API, with a fixed radius
- Part 5: Filter search results to occur within boundaries
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:
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:
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.