Last active
December 31, 2024 15:17
-
-
Save ultrox/9fd8be5f05cb8dbf13fd27e311224dc3 to your computer and use it in GitHub Desktop.
Lerp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Linearly interpolates between two values (`start` and `end`) based on a given interpolation factor `t`. | |
* | |
* @param start - The starting value of the interpolation. | |
* @param end - The ending value of the interpolation. | |
* @param t - A factor between `0.0` and `1.0` that determines the weight of the `end` value. | |
* - `t = 0.0`: Returns the `start` value. | |
* - `t = 1.0`: Returns the `end` value. | |
* - `0.0 < t < 1.0`: Returns a value between `start` and `end`, weighted proportionally to `t`. | |
* - Values outside the range `[0.0, 1.0]` result in extrapolation beyond the `start` and `end` range. | |
* | |
* @returns The interpolated value between `start` and `end`. | |
* | |
* @example | |
* ```typescript | |
* const value = lerp(0, 10, 0.5); // Returns 5 (midpoint) | |
* const value2 = lerp(0, 10, 0.0); // Returns 0 (start) | |
* const value3 = lerp(0, 10, 1.0); // Returns 10 (end) | |
* const value4 = lerp(0, 10, 1.5); // Returns 15 (extrapolation) | |
* ``` | |
*/ | |
const lerp = (start: number, end: number, t: number): number => { | |
return start * (1 - t) + end * t; | |
}; | |
// LERP as I lerend it first time. | |
// This is not the LERP you want to use, because | |
// how naive and 'dirty' it is. | |
// no containment, uses global state, lerp itself mutate stuff. | |
// raf not canceled, never clamped, etc | |
const circleEl = document.querySelector('.circle'); | |
const currentPoint = { x: 0, y: 0 }; | |
const targetPoint = { x: 0, y: 0 }; | |
function lerp() { | |
currentPoint.x = currentPoint.x + (targetPoint.x - currentPoint.x) * 0.1; | |
currentPoint.y = currentPoint.y + (targetPoint.y - currentPoint.y) * 0.1; | |
circleEl.style.setProperty('--x', currentPoint.x); | |
circleEl.style.setProperty('--y', currentPoint.y); | |
requestAnimationFrame(lerp); | |
} | |
requestAnimationFrame(lerp); | |
document.body.addEventListener('pointermove', (event) => { | |
targetPoint.x = event.clientX; | |
targetPoint.y = event.clientY; | |
// circleEl.style.setProperty('--x', event.clientX); | |
// circleEl.style.setProperty('--y', event.clientY); | |
}); |
Author
ultrox
commented
Dec 27, 2024
•
- start ⋅(1−t) "how much of the start is left." ( t = 0 : all start is left)
-
- (Add)
- end⋅t "how much of the end is added."
const lerp = (curr, next) => {
const delta = next - curr;
if (Math.abs(delta) < 0.01) return next;
return curr + (next - curr) * 0.13;
};
function createLerper() {
let target = 0;
let current = 0;
let af;
const observers = new Set();
function animate() {
current = lerp(current, target);
observers.forEach((observer) => observer({ current, target }));
if (current === target) return;
af = requestAnimationFrame(animate);
}
return {
update: (value) => {
cancelAnimationFrame(af);
target = +value;
animate();
},
subscribe: (fn) => {
observers.add(fn);
fn({ current, target });
}
};
}
const lerper = createLerper();
// Diamond Slider
// https://codepen.io/team/keyframers/pen/ExWGGpX?editors=0010
const lerp = (curr, next) => {
const delta = next - curr;
if (Math.abs(delta) < 0.01) {
return curr;
}
return curr + (next - curr) * 0.13;
};
// Reactive Timeframe Concept
// https://codepen.io/davidkpiano/pen/vxZEoO
function createFollowAnimation({ onUpdate }) {
let af;
const state = {
targetPoint: { x: 0, y: 0 },
currentPoint: { x: 0, y: 0 }
};
function lerp(start, end, t) {
const k = (s, e) => {
const delta = e - s;
if (Math.abs(delta) < 0.01) {
return e;
}
return s * (1 - t) + t * e;
};
return {
x: k(start.x, end.x),
y: k(start.y, end.y)
};
}
function animate() {
console.count("fko");
cancelAnimationFrame(af);
state.currentPoint = lerp(state.currentPoint, state.targetPoint, 0.1);
if (state.currentPoint === state.targetPoint) {
return;
}
onUpdate(state.currentPoint);
af = requestAnimationFrame(animate);
}
function updateTargetPoint(x, y) {
state.targetPoint = { x, y };
}
return {
start: () => {
document.body.parentNode.addEventListener("pointermove", (event) =>
updateTargetPoint(event.clientX, event.clientY)
);
animate();
}
};
}
// Usage:
const animation = createFollowAnimation({
onUpdate: (point) => {
box.style.setProperty("--x", point.x);
box.style.setProperty("--y", point.y);
}
});
animation.start();
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment