back
87 comments
This isn't linear interpolation, but it is a discrete approximation of a linear differential equation (note that all linear functions can be described as lerps, but that's uninteresting in this case):

x'(t) = 0.2(b - x(t))

where b is the final position, x is the current position as a function of time, and t is time.

Solving this linear differential equation gives us:

x(t) = b + e^(-0.2t)

which up to a change in constants is what easings.net would call easeOutExpo [1]. So the usual way you would describe this "lerp" in computer graphics would be "exponential ease-out". This solved version of the ODE also gives us a function that isn't dependent on the framerate, so in practice the direct form with the exponential function is preferable for implementation (unless you're in a very constrained environment).

[1]: https://easings.net/#easeOutExpo

Good explanation. But one thing that might not be obvious is that "b" is a moving target in the article (and in many cases where this technique is used), so using your equation, moving "b" by one unit in a given frame will also move x(t) by one unit, causing it to feel a bit faster/more aggressive.

Your final equation will guarantee that you will end up at (a given closeness to) the target at a given time, wherever that target might be, and however fast it might be moving away.

Using the (poorly-named) approach in the article gives you a subtly different behavior, where the easing is essentially "reset" each frame. If you "run away" from the easing object at the right speed, you can delay it reaching you for an arbitrarily long amount of time, which has a different feel, and different practical consequences depending on the context. This is demonstrated in the "Follow the mouse" example in the article.

I believe this is actually an example of what's known as a "proportional derivative controller", which is effectively an underdamped spring. With a PD controller, the further the target points are apart, the faster the interpolation.

Lerp, on the other hand, is linear; the interpolation speed should not change:

Lerp(int A, int B, float t) { return (1.f-t)A + (tB); }

In the example implementation I present, it's assumed that t is pre-modulated by the framerate delta time, and within the bounds (0.f, 1.f)

You can easily make a PD controller out of a lerp, but (without a lot of gymnastics) you can't create a lerp out of a PDC.. at least as far as I know.

In PID terms, this is even simpler yet - just a proportional controller. Only the error between the target and current position are acted upon by a single (proportional) gain:

(targetPosition.x - position.x)0.2 == ekP

A derivative term would be applied to the difference between the previous and current error, usually in order temper the rate of change. D terms can be a proper headache in practice, especially if you have any noise in your system...

It's also an example of a PID controller with the integral and derivative terms set to zero: https://en.m.wikipedia.org/wiki/PID_controller
It’s funny, a while back I was working on a video game and starting writing a dumb AI driver for a semi-physical car. I started by doing the thing in the article, using the P term only, for the steering input to the car. It’s the same thing I’d done for follow-cameras in games with success.

Much to my surprise, steering a car in proportion to how far off track it is turns into an oscillation, and the more you damp the proportional term, the more unstable and divergent the oscillation gets! Well I’d had differential equations in college, but when someone told me that me PID controllers were the solution to my driving AI, I was very surprised I’d never heard of them before.

PID controllers are neat, they’re almost like a suspension shock with an adjustable spring that has damping and rebound controls, but unitless and you can plug them into anything.

That is lerp. Yes yes yes. Ugh.

I've written that exact function in multiple languages for probably a dozen projects or more.

To my mind, the lerp thing makes the direct interactions in the demos look slow, smooth, and imprecise instead of fast, sharp, and immediately correct.

Where lerp would be great is showing indirect results of some actions: a non-obvious effect shown as a slower animation may give a better idea of what is happening, when you were not tracking the value previously. The scrolling demo gives a glimpse of it, but it's still a bit too direct to benefit seriously.

Without context, the animation applied to a basic interaction seems like it's getting in the way of User Interaction

But as you hint, in many situations a gradual change of the presentation will allow a user a lot more awareness of the presentation and it's interconnections as a whole.

With scrolling, the idea is usually you're looking at a massive block of text with some images. Why are you scrolling?

Sometimes, you may know exactly where on the page you're trying to go -- in which case lerp will interfere with the interaction.

But in most cases, your using the scroll feature to skim and find the correct place, in which case an animated scroll will serve the user better since the content will have a predictable location throughout the presentation.

> To my mind, the lerp thing makes the direct interactions in the demos look slow, smooth, and imprecise instead of fast, sharp, and immediately correct.

I think the examples are made this way specifically for you to notice the effect. Animations can, and should be employed sparingly and made fast. However, there are quite a few places where adding just a little touch of animation helps immensely: buttons that react to the touch, slight dampening of the scroll when you jump to an anchor link (so that the eye adjusts to the new page position), state changes etc.

Personal gripe: Older versions of iOS were quite good with that, but then they've made a ton of animations, and made them slow.

Yes. The examples were clear, but seems like not the best use cases for this. My impression is that it was smoother but laggy and imprecise.

I wouldn't want it for an object I was directly controlling (what's needed is faster sampling rate), but likely great for less controlled objects. Or maybe just change the parameters to make it track more closely (adjustible)?

I wonder if I'm falling into the trap where a moderately interesting article with something clearly misleading about it makes me want to correct things. "Drives engagement" I suppose (:

But yeah, please don't call this lerping, as others have mentioned.

Real lerp is one of a a whole constellation of easing functions[1][2], and indeed playing with variations of "how does f(t) vary from 0–1 as t varies from 0–1" is super useful in all sorts of contexts.

But "get X% closer to the (moving) target every frame" is a more complicated thing. It is not just a f(t) easing function, even if the math overlaps.

In fact, this confusion has already had articles written about it[3] so I swear it's not just me!

I don't think the approach mentioned in TFA is wrong per-se. Situations vary, and it can be useful. But there is enough terminology confusion in CS already.

One downside of the approach: you never know _when_ you'll reach your target. Also, especially with the slider example, the feedback feels much more "sloppy." I much prefer the tighter-feeling simple version. But in some cases, like when an enemy is chasing you in a video game, it can be a useful simple-to-implement technique. Be sure to cap your min/max velocities, though.

[1] https://github.com/Michaelangel007/easing

[2] https://easings.net/ (CSS-centric)

[3] https://medium.com/swlh/youre-using-lerp-wrong-73579052a3c3

Ironically, the person who posted this article on lerp also posted the article you linked to in [3], which calls out exactly the problem with this article. What a weird series of events..
That interpolation (which isn't a lerp) is framerate dependent. On slower devices, it will be exponentially slower, on faster devices it's going to be near-instant.

Anytime you see an interpolation that does not use a time-component, that interpolation will be (wildly) different on different devices.

IDK, on my fast desktop computer it's still a slow and bad simulation of inertia.
Sure, but this is a demo seemingly targeted at people who design interactions, not definitive documentation for front-end developers. In any animation environment with this much control, taking the tick delta or some equivalent into consideration is trivial-- a couple of lines at most. But adding implementation details irrelevant to the core mechanism unnecessarily increases the cognitive load for folks who don't parse code for a living.
Sorry, just my feeling but I hate when UI lags behind my input needlessly. I want immediate feedback; get out of my way. This is especially true on page scroll.
What? You don't like pushing a button and waiting for it to register that you pushed it but it doesn't so you push it again, but somehow it did register and something popped up in it's place a millisecond before you pushed it again, and now you just pushed something that you didn't intend to?
You know what's really great, too?

When a website is loading dynamically, and the UI is being reshaped on the fly with unpredictable delays, so you move your mouse to the widget you want to interact with and, by the time you actually do something with it, enough of the page has loaded that your interaction hits a completely different widget! Fun!

Yes, I use the Internet Archive's Firefox add-on, why do you ask?

I generally loathe websites that mess with my scrolling.

That being said, there's a place for everything! And I like the author's simple implementation.

The point of these transitions is to tell user object's trail of movement so user aren't confused by the sudden change in position, but most people use them mindlessly in UI to make stuff feel unresponsive. For example lerping on scrolling is absolutely useless, because scrolling is directly triggered by user input, they would understand perfectly any Y movement of the viewport is caused by their input, the lerp will just leave impression of lagginess or even confusion. I'd argue UI rarely needs transitions, these are mostly useful in games and simulations.
The input on Fortnite's aiming system has two response curve settings Exponential and Linear. For some reason the game defaults to Exponential. Until I found that setting, I was CONSTANTLY fighting with the inputs. For years I'd go to aim and my reticle would eventually end up where I wanted it, but too late so I'd pull back to try to aim it where the person moved and repeat.

Changing it to linear (I'm assuming it's 1:1 with my input now, it feels that way) was a game changer! I don't understand why companies seem so bad at the most basic things. Just let me input, interpolation just adds lag and unresponsiveness.

A canonical lerp is a linear interpolation. What this post describes is repeated linear interpolation towards a target with a fixed interpolation ratio, i.e. exponential averaging aka a 1 pole lowpass filter.

A more serious treatment of the subject would've touched upon this. It would also not call this "lerp" because that name is already taken for the general form.

For example, you can fix the laggy feel of a single exponential average by repeating it. This creates a two pole lowpass filter with a steeper transient.

Z transforms from DSP provide a more formal treatment of the subject.

"An In-Depth look at Lerp, Smoothstep, and Shaping Functions"[1] by SimonDev is the best 8min introduction to Lerp for a software engineer that I saw.

[1] https://www.youtube.com/watch?v=YJB1QnEmlTs

Take this as a lesson - if you ever want criticism on HN, post something about messing with animations on a page. Scrolljacking is a cardinal sin around these parts.

On another note - is it true that this would mean the animation frame function will run infinitely (even though the render will not re-render under a certain threshold)?

The feedback to this article seems hyperbolically vicious. But frontend web dev always feels like a field with a lot of very sharp opinions about things.

In some contexts, yes using Lerp to go half way to a target can lead to running forever which can cause timing bugs. If you lerp halfway to a specific point each frame and trigger an event when you reach that point then it runs infinitely. In practice it just runs until the rounding error goes to zero, but the timing for this can be weird and it adds an unwanted delay. I once spent ~2 days changing all the animations in a program to switch from using this type of smoothing to using lerp on an animation curve with a definite time duration. Exponential filters are good for smoothing a continuous parameter, but they should not be used on a bounded interval where the end point matters.

This is not linear interpolation or a PD controller. This is an exponentially weighted moving average (AKA, a Kalman filter where your model is that the data is constant).

https://en.wikipedia.org/wiki/Moving_average#Exponential_mov...

https://en.wikipedia.org/wiki/EWMA_chart (note the formula for z_i)

> AKA, a Kalman filter where your model is that the data is constant

This feels like nuking a mosquito.

Scrolling lerp is the easiest way to ruin your website
That's not lerp. Lerp moves the same amount every frame (for same time delta)
Please don't. This only looks pleasant on the first time you look at it. Now if you need to do hundreds of interactions per day, you want ugly, sharp and precise. Imagine if my text editor decided to "lerp" everything. I'd go insane.
Lerp: for that laggy, scroll-jacked feeling. The feeling that tells you, This is a Serious Modern Website. It has been Designed. By a Designer.
Lerp is life. I built my whole game design toolkit around my meditations on Lerp.

The fundamental truth is that a float can disguise itself readily as a bool, but the opposite is not true. A bool cannot pull off the float's mustache.

A digraph(*) of candy coated floats can simulate the universe, forward and backwards. With rewind and seeking to any point.

Neat, one of the best tricks in the creadev toolbox! ;)

Shameless plug: https://github.com/titoasty/zmooth I just published a JS library to easily make smooth interpolations, just by setting a "to" value (after doing it by hand for years) I hope you'll find it useful!

The examples shown are all Gerp rather than Lerp.
Another example of designers obsessed with pretty things instead of usability. The 'LERP' example is soggy.
I don't like this, personally. It increases my perception of "lag", and I prefer things on my computer not to lag. It might be nice for animation outside my control, but it should not affect my usage of any type of UI (be it touch or pointing device).
As soon as computers were fast enough, people started to experiment with this stuff:

https://www.youtube.com/watch?v=L41oIvre9K0

How useful it is, is debatable, since it inherently adds lag to user input.

I like the concept of https://en.wikipedia.org/wiki/Convex_combination as a way to think of a single iteration of this 'lerp'.
Oh these rubberbandy effects are just awful (at least in the two examples of scrolling and circle following the mouse) - they break the immediacy of the feedback mechanism between my actions and their effect
https://en.wikipedia.org/wiki/Linear_interpolation

What is described in this blog post is not lerp.

Lerp is also not worth a blog post.

Since I'm not very bright, I tried first example (ball following your mouse) and thought that's cool and very responsive and smooth animation! Then I tried Lerp example...
Isn’t there a Zeno’s Paradox problem with this? Don’t you need a minimum delta otherwise you’ll forever be 20% closer?
Good lord gonna add this thread as another exhibit for why I sometimes hate HN.
so this is the smooth scroll thingy?
derp
> Acknowledgement of Country

> I acknowledge the Gubbi Gubbi people, the Traditional Owners of the land and waterways where I live. I would like to pay my respects to Elders past, present and emerging.

What on earth has this got to do with linear interpolation? Odd punchline to a decent article.