Animated Routes with MKMapView

Creating delightful, animated routes for your user’s journey

Apple’s MapKit lets you place custom overlays on specific map coordinates, which will then be rendered as part of the map and will move along with any map panning and movements.

One of the types of overlays you can add is a Polyline. A polyline is basically a group of Coordinates describing a route on the map. For example, you could represent a route between two coordinates on the map, like so:

Gett together route

Rendering a Polyline is a relatively straightforward task, but we wanted to take it a step further and present an animated version of this route, to convey to the users a feeling of direction and distance to their destination.

In this blog post, you’ll build a naïve implementation to animate your MKPolyline route on top of a MKMapView. This isn’t necessarily the most optimized solution, but is merely for educational purposes.

What you’ll end up with

A polyline animated on top of a Map View

The problem?

Unfortunately, the most common map providers like Apple or Google, do not provide an out-of-the-box solution to animate polylines. When you provide a polyline to any of these Map SDKs, all they would do is to simply render them immediately on the map.

Applying a Polyline

First, you should understand how to apply a single polyline to your map.

Note: For this specific tutorial, you’ll use Apple’s MapKit. Even though other SDKs behave differently, the drawing technique will mostly remain the same :)

Assuming you have an array of coordinates, you’d want to instantiate a MKPolyline object:

Creating a Polyline from an array of Coordinates

You’ll be handling the rendering of the overlays in MKMapViewDelegate’s delegate method — mapView(_:rendererFor:).

You’ll want to provide a different renderer for different types of overlays, such as markers or polylines. For your specific case, you’ll simply render a polyline on the map:

Basic polyline rendering of MKMapView

Now that you have a renderer, all you need to do is to actually add a polyline to your MKMapView instance:

mapView.addOverlay(polyline)

Calling addOverlay will trigger the aforementioned delegate, which will cause the renderer to instantly apply the polyline on the map 😃

An MKPolyline rendered on an MKMapView.

׳Animating your Polyline

Now that you have your basic polyline drawn on the map, you‘ll need to render the polyline in small segments to create the animation effect yourself.

The technique you’ll use for this post will be to cut the polyline into smaller polylines — segments — in succession, where each of the segments will include the previous one.

Simplistic example of polyline segmentation in an accumulating manner.

You’ll be using a repeating Timer to iterate over your coordinates, and calculate the appropriate accumulated segments.

Add a Timer property to your View Controller:

Time to create your animation method, where the beef of the work will be done. Add the following empty method to your View Controller:

Route animation method signature

The method will receive an array of coordinates, the total animation duration, and an optional completion closure.

Next, let’s set up some constants. Add the following code inside your new method:

Here, you decide how many segments to render the polyline with. The more coordinates you have, the higher the drawing resolution and smoothness will be.

Next, implement the timer logic. Add the following to your method immediately after the last piece of code:

Add a Drawing Timer for the Polyline segments

That’s about it for the drawing logic! 🧙‍♀️🎉

Your new method will render your polyline in an animated way by splitting it into segments, as shown above and spacing out the drawing of each segment. Cool! 😎

Did you notice the bug, though?

We never remove the previous polyline segments that were rendered, which means all drawn polyline segments we drew will be rendered on the map along with the newest segment, and will also never be released from memory.

To fix our bug, add a variable to store the previous polyline segment that was drawn, and remove it from the map on each animation iteration. with that, your complete method should look like this, notice the new previousSegment property:

Final method

Did we squash that bug? 🐛

You can check how many MKPolyline objects are currently retained by your application by clicking the Debug Memory Graph icon while your app is running, and filter the results for MKPolyline. Easy peasy! 💪

Wrapping up

I hope you’ve enjoyed this quick post on how to easily achieve animated polyline drawing for your MKMapViews. As mentioned earlier, this technique applies to any other Map SDK — I encourage you to experiment with the various options.