Implementing a Parabolic Jump Interaction for Bottom Navigation with CSS3 Mask and JavaScript
This article explains how to create a bottom navigation bar that jumps along a parabolic trajectory using a mathematical formula for the curve, CSS3 mask and radial‑gradient techniques, and a requestAnimationFrame‑driven JavaScript animation loop.
In this tutorial the author describes the motivation and implementation of a "parabolic jump" interaction for a bottom navigation bar, originally inspired by a UI video from a previous employer.
Parabolic Motion
The motion is derived from the classic quadratic equation y = a * x * x + b * x + c . Assuming the curve passes through the origin (0,0) gives c = 0 . With a constant a and known start and end points, b can be calculated as b = (y2 - a * (x2 * x2)) / x2 . Once a , b , and c are known, the full trajectory can be computed.
/**
* @param target 目标点的x,y坐标
* @param x 当前x坐标
* @param a 常量,决定曲率
*/
const curve = (target : { x : number, y : number }, x : number, a : number = 0.001) => {
let b = (target.y - a * (target.x * target.x)) / target.x;
let y = a * (x * x) + b * x;
return y;
}CSS3 Mask Effect
The visual hole effect is achieved with a CSS mask combined with a radial gradient. The mask syntax mirrors the background property.
background-image: radial-gradient(circle at 50% 0upx, transparent 200upx, white 200upx);Mask example:
-webkit-mask: radial-gradient(circle at 50rpx 0rpx, transparent 45rpx, #999999 45rpx);Images illustrate the resulting mask and gradient effects.
Animation with requestAnimationFrame
To achieve a smooth transition, the author uses requestAnimationFrame to update the position each frame based on the calculated curve.
/* @param target 目标位置
* @param time 运动时长 */
const move = (target, time) => {
let distance = target - circleLeft.value;
let speed = distance / (time / 60);
let isMoveLeft = circleLeft.value > target;
let sourceLeft = JSON.parse(JSON.stringify(circleLeft.value));
const resetStatus = () => {
cancelAnimationFrame(timer);
circleTop.value = 0;
circleLeft.value = target;
}
let animate = () => {
circleLeft.value += speed;
circleTop.value = curve({ x: distance, y: 0 }, circleLeft.value - sourceLeft);
if (isMoveLeft) {
if (circleLeft.value <= target) resetStatus();
} else {
if (circleLeft.value >= target) resetStatus();
}
timer = requestAnimationFrame(animate);
}
animate();
}The animation updates the horizontal position, computes the vertical offset using the parabolic formula, and stops when the target is reached, resulting in a silky motion.
Final Result
The completed effect shows a bottom navigation bar where the active icon follows a smooth parabolic jump, with a masked radial gradient creating a visual hole that follows the moving element.
Feel free to try implementing this interactive navigation bar yourself.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.