Spring easing functions

pull/5579/head
Adam Rackis 5 years ago
parent 65104e8b2a
commit 216ba82e8a

@ -1,3 +1,5 @@
import { springFrames } from "svelte/motion";
/*
Adapted from https://github.com/mattdesl
Distributed under MIT License https://github.com/mattdesl/eases/blob/master/LICENSE.md
@ -169,3 +171,35 @@ export function sineIn(t: number) {
export function sineOut(t: number) {
return Math.sin((t * Math.PI) / 2);
}
const springEasing = (frames, inDirection = true) => t => {
t = inDirection ? t : 1 - t;
const indexPrecise = t * frames.length;
const indexExcess = indexPrecise % 1;
const a = frames[indexPrecise - indexExcess];
let b = frames[indexPrecise - indexExcess + 1];
if (b == null) {
b = a;
}
return indexExcess ? a + (b - a) * indexExcess : a;
};
export function springEnter(from, to, opts) {
const frames = springFrames(from, to, opts);
return {
duration: (frames.length * 1000) / 60,
easing: springEasing(frames)
};
}
export function springLeave(from, to, opts) {
const frames = springFrames(from, to, opts);
return {
duration: (frames.length * 1000) / 60,
easing: springEasing(frames, false)
};
}

@ -2,14 +2,41 @@ import { Readable, writable } from 'svelte/store';
import { loop, now, Task } from 'svelte/internal';
import { is_date } from './utils';
interface TickContext<T> {
interface TickContext {
inv_mass: number;
dt: number;
opts: Spring<T>;
opts: SpringOpts;
settled: boolean;
}
function tick_spring<T>(ctx: TickContext<T>, last_value: T, current_value: T, target_value: T): T {
export function springFrames(from, to, opts: SpringOpts) {
Object.assign(opts, { stiffness: 0.15, damping: 0.8, precision: 0.01 });
let value = from;
let last_val = from;
let dt = 0.25; //WTF???
const values = [from];
let ctx: TickContext;
do {
ctx = {
inv_mass: 1,
opts,
settled: true,
dt,
};
const next_value = tick_spring(ctx, last_val, value, to);
values.push(next_value);
last_val = value;
value = next_value;
dt = 1;
} while (!ctx.settled);
return values;
}
function tick_spring<T>(ctx: TickContext, last_value: T, current_value: T, target_value: T): T {
if (typeof current_value === 'number' || is_date(current_value)) {
// @ts-ignore
const delta = target_value - current_value;
@ -109,7 +136,7 @@ export function spring<T=any>(value?: T, opts: SpringOpts = {}): Spring<T> {
inv_mass = Math.min(inv_mass + inv_mass_recovery_rate, 1);
const ctx: TickContext<T> = {
const ctx: TickContext = {
inv_mass,
opts: spring,
settled: true, // tick_spring may signal false

Loading…
Cancel
Save