This article should have started here.
Not with "animation principles." Not with a gallery of clever demos. Just with basic mechanics.
If motion on screen feels believable, it is usually because a few physical ideas are behaving coherently:
- position
- velocity
- acceleration
- force
- mass
- damping
That is enough to explain a large amount of interface motion, game feel, and simulated movement.
Start with State
In one dimension, the minimum useful system is:
- position:
x - velocity:
v - acceleration:
a
The update step is:
v = v + a * dt
x = x + v * dt
dt is the timestep. It means: how much time passed since the last update?
That is the first idea to keep straight:
- acceleration changes velocity
- velocity changes position
Force and Mass
Newton gives the core relationship:
F = m * a
a = F / m
The same force affects a light body and a heavy body differently.
- small mass: responds quickly
- large mass: responds slowly
That is where "weight" starts to come from. Not from shadows or blur, but from response.
Python: Constant Force on a Mass
x = 0.0
v = 0.0
force = 12.0
mass = 3.0
dt = 1 / 60
for frame in range(120):
a = force / mass
v = v + a * dt
x = x + v * dt
print(frame, round(x, 3), round(v, 3))
Nothing fancy is happening here. That is the point.
Gravity
Gravity is just acceleration acting downward.
a = g
v = v + g * dt
y = y + v * dt
The useful mental model is:
- gravity does not directly move the body
- gravity changes the velocity
- the velocity accumulates over time
That is why falling motion curves instead of moving in a straight line.
Python: Falling Rectangle
y = 0.0
v = 0.0
g = 9.81
dt = 1 / 60
for frame in range(90):
v = v + g * dt
y = y + v * dt
print(frame, round(y, 3), round(v, 3))
Springs
Springs matter because many useful motions are really "return to equilibrium" motions.
Hooke's law:
F_spring = -k * x
Where:
kis stiffnessxis displacement from rest
The negative sign is the important part. The spring force always points back toward equilibrium.
Python: Spring Force
x = 120.0 # displacement from rest
v = 0.0
k = 40.0
mass = 1.0
dt = 1 / 60
for frame in range(180):
force = -k * x
a = force / mass
v = v + a * dt
x = x + v * dt
print(frame, round(x, 3), round(v, 3))
Damping
If you only apply the spring force, the object can overshoot for too long. Real systems usually lose energy.
A simple damping term is:
F_damping = -c * v
Now the total force becomes:
F_total = -k * x - c * v
This is one of the most useful equations in motion work. It explains why something returns, overshoots, and eventually settles.
Python: Spring with Damping
x = 120.0
v = 0.0
k = 40.0
c = 12.0
mass = 1.0
dt = 1 / 60
for frame in range(180):
force = -k * x - c * v
a = force / mass
v = v + a * dt
x = x + v * dt
print(frame, round(x, 3), round(v, 3))
Collision and Energy Loss
When a body hits a floor or wall, it can reverse direction. But if it keeps all of its energy, the result often feels too perfect.
A common approximation is:
v_after = -e * v_before
Where e is restitution.
e = 1.0means no energy losse < 1.0means some energy is lost
That is enough to explain why each bounce becomes smaller.
Python: Falling and Bouncing
y = 20.0
v = 0.0
g = 9.81
e = 0.7
floor = 300.0
dt = 1 / 60
for frame in range(240):
v = v + g * dt
y = y + v * dt
if y >= floor:
y = floor
v = -e * v
print(frame, round(y, 3), round(v, 3))
What This Has To Do with Interface Motion
A lot of UI motion problems are really small physics problems in disguise.
Questions like these are usually better than "Which easing curve should I use?"
- What is the moving body?
- Does it have mass?
- Is there a return force?
- Is energy being lost?
- Should the motion settle, glide, or bounce?
If you can answer those, the motion usually becomes easier to build.
The Main Point
The article does not need nine flashy examples.
A rectangle mass, a force arrow, a spring, and a few formulas are enough to teach the important part.
Once the mechanics make sense, the visual style can come later.