Input smoothing

You can easily add input smoothing to pointer tracking using some light functional composition.

Drag this ball to see pointer tracking without smoothing:

And now with smoothing applied:

Add smoothing

We can use the smooth transformer to apply smoothing to any numerical value.

smooth works by passing a smoothing amount, in milliseconds. This is the duration over which movement will be averaged. So, high numbers equal greater smoothing.


Importantly, a new instance of smooth must be created for each value we want to smooth. This is because the returned function refers to an internal average value. If we pass it multiple values from different sources, it can’t work!

Multi-axis smoothing

So, our pointer might originally look like this:

pointer({ x: 0, y: 0 })
  .start(({ x, y }) => /* unsmoothed output */)

To apply smoothing on both x and y, we can use the transformMap transformer along with smooth:

import { pointer, transform } from 'popmotion';
const { transformMap, smooth } = transform;

pointer({ x: 0, y: 0 })
    x: smooth(200),
    y: smooth(200)
  .start(({ x, y }) => /* smoothed! */)

Single-axis smoothing

If we’re just tracking a single axis, we don’t even need transformMap:

pointer({ x: 0, y: 0 })
    ({ x }) => x,
  ).start((x) => /* smoothed x axis */)


By using smooth, we can apply smoothing to not just pointer output, but that of any action.

More examples of pipe and functional composition can be found in the value pipelines tutorial.