Let animation keys ease with Sine to Bounce in, out or in-out
A key could only ease quadratically, which makes quick moves like a sword swing feel soft. Animators know the Penner curves from CSS, GSAP and Unity, so a key now offers all of them. - Ten curves (Sine, Quad, Cubic, Quart, Quint, Expo, Circ, Back, Elastic, Bounce), each in, out and in-out, next to Linear and Step. - The inspector shows two fields instead of one long list: Easing, and Direction only when a curve is picked. Switching the curve keeps the direction. Coming from Linear or Step starts at in-out. - Old projects keep working. ease-in/out/in-out now read as Quad and are still saved under that name. New curves save as cubic-out, back-in-out and so on. - Back and Elastic overshoot on purpose. A number property with min or max is clamped in play and preview, so a Back in from scale 0 does not flip the sprite. trackWriteAt now takes the property definition, and animatedKind* is renamed to animatedDef*. - The timeline marker still shows only the direction. - In-out is built for every curve from its in-curve and its mirror. easings.net uses own constants for Back and Elastic in-out, so our Back in-out winds up about 5 % instead of 10 %. Tests: - ./check.sh: 165 files, 2413 tests, CHECK EXIT 0. - 12 new unit tests in tests/core/easing-curves.test.ts: round trip of all 30 values, start/end/midpoint of every curve, reference values, only Back and Elastic leave 0..1, clamping in play and preview, unknown values are rejected. - e2e 25: ALL PASSED, 28 checks. New 25b-ii (3 checks) clicks both fields and undoes the four choices. Check sum 1393 -> 1396. - Counter-checks, each fails its test: no clamping (2), Quad saved as quad-* (2), mirrored in-out wrong (2), curve lookup with `in` instead of Object.hasOwn (1), no Direction field (e2e 25). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
94749b4f3e
commit
147f8ffbea
9 files changed
+500
-74
No files matched your search
@@ -10,6 +10,7 @@ import {
|
||||
} from '../../core/commands/animationCommands';
|
||||
import {
|
||||
animationPlayheadAt,
|
||||
easingOf,
|
||||
fpsOf,
|
||||
frameCount,
|
||||
hasKey,
|
||||
@@ -683,8 +684,8 @@ export class TimelineCanvas extends Widget {
|
||||
|
||||
/**
|
||||
* A key's outline tells its easing: the right half is the start of the way to the next key, the left
|
||||
* half its end, and a round half is a slow one. Linear is the diamond, ease-in-out the circle, a step
|
||||
* – which holds – the square.
|
||||
* half its end, and a round half is a slow one. Linear is the diamond, any curve in-out the circle, a
|
||||
* step – which holds – the square.
|
||||
*/
|
||||
function drawKeyShape(
|
||||
g: Graphics,
|
||||
@@ -694,8 +695,9 @@ function drawKeyShape(
|
||||
half: number,
|
||||
): Graphics {
|
||||
if (interpolation === 'step') return g.rect(x - half * 0.75, y - half * 0.75, half * 1.5, half * 1.5);
|
||||
const slowStart = interpolation === 'ease-in' || interpolation === 'ease-in-out';
|
||||
const slowEnd = interpolation === 'ease-out' || interpolation === 'ease-in-out';
|
||||
const { direction } = easingOf(interpolation);
|
||||
const slowStart = direction === 'in' || direction === 'in-out';
|
||||
const slowEnd = direction === 'out' || direction === 'in-out';
|
||||
g.moveTo(x, y - half);
|
||||
if (slowStart) g.arc(x, y, half, -Math.PI / 2, Math.PI / 2);
|
||||
else g.lineTo(x + half, y).lineTo(x, y + half);
|
||||
|
||||
Reference in new issue
Block a user