Google Maps is an excellent – probably the best – solution for displaying an interactive map on your website. A few years back, though, they decided to put a limit on their free API, beyond which you begin getting charged. While this decision makes total sense, and the free limit is high enough for most use cases, it has an important drawback: to use the API, you need to create an account, providing a valid credit card. That can be no issue for a one-off site, but if you are a web developer can cause a few headaches, as you have to ask each client to create a billing account and enable the required APIs. Clients can get overwhelmed by that, and supporting them could eventually cost you a few extra hours of work.
Therefore, searching for an alternative using data from OpenStreetMap, which has no such limits, was the reasonable thing to do, at least for projects that need no complex implementations, but just a map with a few locations on it (which is the majority of my projects). Searching at the WordPress’ repository can give you plenty of such plugins. More or less, they fall in two distinct categories:
- Those that organize locations as custom post types, retrieving the maps with shortcodes. Some of them are quite powerful, with a handful of features. Managing them, though, becomes too complicated. First, you need to (sometimes painstakingly) create your locations either as post types or as repeater fields on a single post type, one location at the time. Then, you get a shortcode which you have to paste on the post/page that you want the map to appear. Those plugins can be excellent solutions for more complicated maps, but not practical enough for our simple use case. Also, using shortcodes when you can have Gutenberg blocks is like sending a fax when you can use email.
- The Gutenberg blocks. They are not many, and they are more user-friendly, but they usually require you to copy the locations’ coordinates, which makes them OK but not great.
The ideal requirements
So, if there were no restrictions at all, how would we want a simple map block to work, for it to be as easy as possible for the non-tech-savvy content manager? After all, Gutenberg allows us to think out of the box here (or should we say, out of the block?). Based on my own needs, I identified the following requirements:
- It should be a Gutenberg block. No shortcodes, and no custom post types. The whole functionality should exist entirely inside the post/page hosting the map.
- It should work out of the box. No setting of API keys, and no options to be set beforehand. Just click on the block and start adding your locations.
- You shouldn’t have to manually add coordinates. Just point and click on the map to drop a marker.
- A marker’s popup should be allowed to accept formatted text, links, and images.
- We live in the Gutenberg era. You don’t need a separate text field to add your popup’s content. You can just open the popup and start typing in it.
- The map should remember the zoom level that you last set when adding your markers.
- You should be able to adjust a few basic things on the map, like height, minimum and maximum zoom, dragging, and clicking behavior.
In the end, we should end up with something like this:
Building the above functionality turned out to be relatively straightforward on the technical front. Gutenberg, leaflet.js and OpenStreetMap were all the tools that we needed. In the process, though, a few interesting UX challenges came up.
Removing a marker
Click-and-drop is probably the most straightforward way to add markers. How do you remove them, though? In general, how should you deal with marker-specific options? For example in a future version of the plugin, you will have the option to add a different icon per marker.
Well, that was an easy one: just keep those options inside the marker’s popup.
Click-and-drop markers is a great feature but it can easily get problematic in two scenarios: when you accidentally quick-click anywhere on the map, and when you click and hold intending to drag.
To work around this issue, a small delay has been added, to create an “opportunity window” where you can perform the drop. That way, accidental quick clicks will have no effect. Similarly, if you fail to release the click quickly enough, you miss your window, as it assumes that you intend to drag.
To identify the opportunity window and make it apparent to the user, the cursor changes to a crosshair, and a notice pops up.
Drop an overlapping marker
When you haven’t zoomed enough and you click-and-drop too close to an existing marker, the new marker appears on top of the old one and you can’t tell if the drop was successful or not unless you either zoom in or drag the marker to see if there is another one underneath. Solving this was as simple as adding a CSS animation to the dropping marker.
Not only does that make the dropping apparent, but it makes our interface more visually appealing, and it’s just a few lines of CSS. Win-win, in all regards!
Sane minimum and maximum zoom levels
The map allows you to set the maximum and minimum limits that the user can zoom on the frontend. What if you set a min-zoom higher than the max-zoom, or a max-zoom lower than the min-zoom? Of course, you could always ignore the illogical values on your frontend, or let leaflet.js deal with it with whatever way it does, but still, your admin interface would make no sense.
To fix this, we need to make sure that whenever one value goes beyond the limits posed by the other, the other value gets updated as well. As a bonus, setting the same minimum and maximum zoom will lock the frontend zoom at that level, practically disabling it.
So far, the plugin has been tested only by me, though I saw no serious bugs. It will probably need some polishing here and there, as well as some important additions. More specifically, the development roadmap includes, among others, features like separate icons per marker, an option to change the map’s colors and styles, a way to import and export the markers to a JSON file, and, probably the most important, a location finder with autocomplete capabilities, as a complementary way of adding locations.
In fact, I consider the location search to be an essential tool for the plugin’s UI to be complete. It’s a big feature, though, which needs some good thinking and careful implementation to make it as user-friendly as possible. So, I thought I’d release that basic version first, so that people start using it, and fix possible bugs before continuing to implement new features.
UPDATE 27-12-2022: Added support for polygons and polylines.
UPDATE 22-09-2020: Place search is ready.
If you think that the above functionality would work well for your needs as well, you can give the plugin a try, downloading it either from wordpress.org or from GitHub and let me know about your impressions in the comments.