John Wika Haakseth

Mappy web developer based in Copenhagen, Denmark 🇳🇴 🇩🇰 🐶 🎸 🏐 🗺 💻

Creating custom webmap animations - part 3 - Adding easing

February 2, 2020

From the previous part, we have a pretty good animation. There is still one more thing to do to create an even more pleasant animation: Easing.

Add easing

Right now our animation is linear. In nature, most motion has an acceleration component to it. This mean that we as humans are used to it, and we should use it in web-animations as well, to make our interfaces more pleasant to use.

I found a good source of easing functions for javascript here, and some nice visualizations here. Google Developers also has a well-written article on the subject. For this example, let's try the following function:

const easeInOutCubic = (t) =>
  t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;

We can then rewrite our createNormalizedLineFeature() function to vary the along length like so:

export const createNormalizedLineFeature = (feature, res = 60) => {
  const alongDist = length(feature) / res;
  const normalizedFeature = {
    ...feature,
    features: [
      {
        ...feature.features[0],
        geometry: { ...feature.features[0].geometry, coordinates: [] },
      },
    ],
  };
  for (var i = 0; i < res; i++) {
    const newCoord = along(
      feature.features[0].geometry,
      alongDist * (i * easeInOutCubic(i / res))
    );
    normalizedFeature.features[0].geometry.coordinates.push(
      newCoord.geometry.coordinates
    );
  }
  return normalizedFeature;
};

By varying the distance between the points on our route, we get a more pleasing result:

In the first part of this series, I said that this method works equally well for other map libraries. To put my money where my mouth is, here is the same example in OpenLayers. OpenLayers even provide their own easing functions we can use.

There are still more things to do for us to improve these animations, but this post is getting long enough. For example:

  • Control duration of animation based on actual time in stead of just frames.
  • Handle framedrops. For instance, if the browser is struggling, fall back to just showing the route.
  • Handle different types of geometries. Routes may consist of multiLineStrings. Also, maybe we want to animate polygons or points?

If you enjoyed this series, or have any feedback, feel free to contact me on twitter. This post is also posted on dev.to, so you can also comment there.

© Copyright 2024 John Wika Haakseth