fix: clean up graph editor

This commit is contained in:
Maze Winther 2026-04-06 13:15:50 +02:00
parent c411edb7c1
commit 79df736431
3 changed files with 66 additions and 52 deletions

View File

@ -62,9 +62,9 @@ function curvePath({ curve }: { curve: NormalizedCubicBezier }) {
const points: string[] = [];
for (let i = 0; i <= CURVE_SEGMENTS; i++) {
const progress = i / CURVE_SEGMENTS;
points.push(
`${toSvgX({ value: getBezierPoint({ progress, p0: 0, p1: curve[0], p2: curve[2], p3: 1 }) })},${toSvgY({ value: getBezierPoint({ progress, p0: 0, p1: curve[1], p2: curve[3], p3: 1 }) })}`,
);
const x = toSvgX({ value: getBezierPoint({ progress, p0: 0, p1: curve[0], p2: curve[2], p3: 1 }) });
const y = toSvgY({ value: getBezierPoint({ progress, p0: 0, p1: curve[1], p2: curve[3], p3: 1 }) });
points.push(`${x},${y}`);
}
return `M${points.join("L")}`;
}

View File

@ -299,13 +299,21 @@ function PresetItem({
);
}
function toThumbX({ value }: { value: number }) {
return THUMB_PADDING_X + value * (THUMB_WIDTH - THUMB_PADDING_X * 2);
}
function toThumbY({ value }: { value: number }) {
return THUMB_PADDING_Y + (1 - value) * (THUMB_HEIGHT - THUMB_PADDING_Y * 2);
}
function CurveThumb({ value }: { value: NormalizedCubicBezier }) {
const points: string[] = [];
for (let i = 0; i <= THUMB_SEGMENTS; i++) {
const progress = i / THUMB_SEGMENTS;
points.push(
`${THUMB_PADDING_X + getBezierPoint({ progress, p0: 0, p1: value[0], p2: value[2], p3: 1 }) * (THUMB_WIDTH - THUMB_PADDING_X * 2)},${THUMB_PADDING_Y + (1 - getBezierPoint({ progress, p0: 0, p1: value[1], p2: value[3], p3: 1 })) * (THUMB_HEIGHT - THUMB_PADDING_Y * 2)}`,
);
const x = toThumbX({ value: getBezierPoint({ progress, p0: 0, p1: value[0], p2: value[2], p3: 1 }) });
const y = toThumbY({ value: getBezierPoint({ progress, p0: 0, p1: value[1], p2: value[3], p3: 1 }) });
points.push(`${x},${y}`);
}
return (
<svg

View File

@ -89,55 +89,61 @@ export function useGraphEditorController() {
[discardPreview],
);
function handlePreviewValue(nextValue: NormalizedCubicBezier) {
if (state.status !== "ready") {
return;
}
const handlePreviewValue = useCallback(
(nextValue: NormalizedCubicBezier) => {
if (state.status !== "ready") {
return;
}
const nextAnimations = applyGraphEditorCurvePreview({
animations: state.element.animations,
context: state.context,
cubicBezier: nextValue,
});
editor.timeline.previewElements({
updates: [
{
const nextAnimations = applyGraphEditorCurvePreview({
animations: state.element.animations,
context: state.context,
cubicBezier: nextValue,
});
editor.timeline.previewElements({
updates: [
{
trackId: state.trackId,
elementId: state.elementId,
updates: {
animations: nextAnimations,
},
},
],
});
hasPreviewRef.current = true;
},
[editor, state],
);
const handleCommitValue = useCallback(
(nextValue: NormalizedCubicBezier) => {
if (state.status !== "ready") {
return;
}
const patches = buildGraphEditorCurvePatches({
context: state.context,
cubicBezier: nextValue,
});
if (!patches) {
return;
}
editor.timeline.updateKeyframeCurves({
keyframes: patches.map(({ keyframeId, patch }) => ({
trackId: state.trackId,
elementId: state.elementId,
updates: {
animations: nextAnimations,
},
},
],
});
hasPreviewRef.current = true;
}
function handleCommitValue(nextValue: NormalizedCubicBezier) {
if (state.status !== "ready") {
return;
}
const patches = buildGraphEditorCurvePatches({
context: state.context,
cubicBezier: nextValue,
});
if (!patches) {
return;
}
editor.timeline.updateKeyframeCurves({
keyframes: patches.map(({ keyframeId, patch }) => ({
trackId: state.trackId,
elementId: state.elementId,
propertyPath: state.propertyPath,
componentKey: state.context.componentKey,
keyframeId,
patch,
})),
});
hasPreviewRef.current = false;
}
propertyPath: state.propertyPath,
componentKey: state.context.componentKey,
keyframeId,
patch,
})),
});
hasPreviewRef.current = false;
},
[editor, state],
);
return {
open,