Turns a drag on the curve editor's canvas into a key's new time and value, or a handle's new offset.
How the precision is kept
A canvas position is mapped linearly to seconds and to the curve's value in 64-bit numbers. A dragged key's time is rounded to 0.001 s before it is stored; its value is stored as computed.
Calculations under this policy
3 calculations in 1 source file. The code is read from the released app when this page loads. It is the calculation people run, not a copy kept for this page.
Moves a key in time and sets one number of its value.
time = max(0, round(t × 1000) ÷ 1000); value = v
The time is rounded to 0.001 s with Math.round before it is stored; the value is stored unrounded. The key is found again afterward by exact equality with the rounded time.
anim/graph.js
lines 95 to 108
ModelCraft 0.8.1
/** A key dragged to (t, v): its time moves (onto another key's time it replaces it) and that number of its value changes. */
export function dragKey(anim, p, t, v) {
const tr = trackOf(anim, p.track);
if (!tr) return anim;
const k = tr.keys[p.i];
if (!k) return anim;
const to = Math.max(0, r3(t));
let a = Math.abs(to - k.t) > 1e-9 ? moveKey(anim, p.track, k.t, to) : anim;
const tr2 = trackOf(a, p.track), k2 = tr2 && tr2.keys.find((x) => x.t === to);
if (!k2) return a;
const val = k2.v.slice();
val[p.comp] = v;
return setPropKey(a, tr2.target, tr2.prop, to, val, k2.ease);
}
A handle dragged
64-bit
The handle's new offset from its key in time and value.
Δt = t − key time (≤ 0 for the left handle, ≥ 0 for the right); Δv = v − key value
Plain 64-bit differences from the key; nothing is rounded here.
anim/graph.js
lines 109 to 119
ModelCraft 0.8.1
/** A handle dragged to (t, v): the other numbers of its key keep their handle values. */
export function dragHandle(anim, p, side, t, v) {
const tr = trackOf(anim, p.track), k = tr && tr.keys[p.i];
if (!k) return anim;
const h = handlePoints(tr, p.i)[side];
let dt = t - k.t;
if (side === 'l') dt = Math.min(0, dt); else dt = Math.max(0, dt);
const dv = h[1].map((x, j) => x - k.v[j]);
dv[p.comp] = v - k.v[p.comp];
return setHandle(anim, p.track, k.t, side, [dt, ...dv]);
}
In detail
Method
Linear map between canvas pixels and the view's time and value ranges.
Number types
64-bit numbers.
Tolerances
A key's time is moved only when it differs from the old one by more than 1e-9 s.
Checked by
bin/test-animation.mjs loads the development build's copy of this file and calls fromPx, dragKey and dragHandle.
Limits
Key times set by dragging lie on a 0.001 s grid and are never negative.
Approach: 64-bit, direct
Every value is a 64-bit number from input to result. Formulas are closed form or a direct solve, and every comparison uses a stated tolerance.