Skip to main content
GDN8 PATIO

About lerp and damp

This note organizes the basics of each and how to choose between them for mouse following.

lerp with a fixed value

lerp() is a function that connects two values along a straight line. In the next code, it advances 10% of the remaining distance from the current value to the target.

function lerp( start, end, progress ) {
	return start + ( end - start ) * progress;
}

currentX = lerp( currentX, targetX, 0.1 );

The 0.1 here is not a rate per second. It is the fraction advanced in one update. At 30fps it runs about 30 times per second, and at 120fps about 120 times, so higher FPS reaches the target sooner.

If you use a fixed-value lerp() for mouse following, the same implementation changes how the follow feels depending on the viewing environment.

damp that uses elapsed time

damp() uses the seconds since the previous frame to calculate how far to advance in that frame.

function damp( current, target, speed, deltaTime ) {
	return lerp(
		current,
		target,
		1 - Math.exp( -speed * deltaTime )
	);
}

speed is how strongly it follows. Larger values approach the target quickly, smaller values slowly. At low FPS it advances more per frame, and at high FPS less per frame, so the position after the same elapsed time stays almost the same. That lets you keep the follow feel aligned even when FPS differs.

Use for mouse following

Next is an implementation that makes an element follow the pointer’s X coordinate.

const item = document.querySelector( '.item' );

let currentX = 0;
let targetX = 0;
let previousTime = performance.now();

function lerp( start, end, progress ) {
	return start + ( end - start ) * progress;
}

function damp( current, target, speed, deltaTime ) {
	return lerp(
		current,
		target,
		1 - Math.exp( -speed * deltaTime )
	);
}

function update( now ) {
	const deltaTime = Math.min( ( now - previousTime ) * 0.001, 0.05 );

	previousTime = now;
	currentX = damp( currentX, targetX, 8, deltaTime );
	item.style.transform = `translateX(${ currentX }px)`;

	requestAnimationFrame( update );
}

window.addEventListener( 'pointermove', ( event ) => {
	targetX = event.clientX;
}, { passive: true } );

requestAnimationFrame( update );

Each time the pointer moves, only targetX changes. currentX approaches targetX each time requestAnimationFrame() runs.

deltaTime is converted from milliseconds to seconds before it is passed. Here it is capped at 0.05 seconds so extreme values do not appear right after reopening a tab and similar cases.

You can compare fixed-value lerp() and damp() following in the mouse follower comparison demo.

When to use which

Use lerp() when you need a single intermediate value, or when progress is already normalized from 0 to 1.

When following a changing target every frame, such as mouse, scroll, or camera, damp() is recommended. It is easier to keep follow speed aligned across FPS, and it is less affected by the viewing environment than repeating a fixed-value lerp().

That does not mean a fixed-value lerp() is inappropriate. The case that needs care is when a fixed interpolation rate is repeated every frame for following.

References

  • ※ This article is an AI translation of the Japanese original.