All Articles

Creating custom webmap animations - Controlling duration

In the previous part, we set up the application, and added animation to the feature we’re adding to the map. Since we added only one point to the line feature for each animation frame, we saw that for longer routes, this could make the animation unbearably long. In addition, due to the line’s topology, some parts of the line might have more points than others, thus making the animation vary in speed:

Ouch! Let’s bring out turf.js to work on the line to make a smooth, predictable animation.

Approach

  • Chop the line into equal parts of line length divided by our desired line resolution.
  • In stead of adding a single point per animation frame, we’ll add number of points divided by number of desired animation frames per animation frame. This lets us control the length of the animation.
  • Finally, when the animation is done, we’ll replace the animated feature with the original one, as doing the previous steps will change its topology some, depending on our line resolution.

Calculating length and finding points along the line using turf.js

In order to get a smooth line of a given resolution we’ll have to do some work on the feature. For this we’ll use turf’s functions length and along. Let’s define a function createNormalizedLineFeature(feature, resolution) that takes a line feature and does the following:

  • Calculate the feature’s distance
  • Based on distance and resolution, calculate “along-distance” for feature (how far between each point). Higher resolution will make the line more detailed, but will demand more computing power.
  • Create feature without coordinates.
  • Use the along function for turf to add coordinates to feature along the original line.

Here is an implementation:

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

Result

Great! Now our animation will be just as fast, no matter how long the feature is. We can use the resolution parameter to make it more or less detailed during animation. Just remember to replace the animation feature with the original route feature when the animation is complete, as we might lose some detail depending on our resolution.

In the next and final part we’ll try to make the animation feel more natural by adding easing.

If you enjoyed this post, 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.