feat(canvas): add leafer GPU renderer and interactive color-boundary crop tool
Introduce a leafer-ui canvas layer that mirrors rendered nodes and drives viewport, node-drag, and alignment-guide updates imperatively, committing React state on idle via startTransition to keep pan/zoom/drag at 60fps. Wire the imperative viewport through wheel zoom, zoom-to, fit-view, and panning. Add a dedicated crop tool: click a node to auto-detect a color-boundary crop region or drag to preselect one, previewed with an on-canvas draft overlay before entering the crop editor. Route uploads through renderContent so the transparent WebP texture feeds the fast display path. Add node --test coverage for the leafer renderer and color-boundary detection. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
|
||||
import { createVectorCropSiblingNode, croppedSvgViewBox, vectorCropRasterSize, vectorCropSiblingSize } from "../src/ui/pages/CanvasWorkspace/canvas/cadCrop.ts";
|
||||
import { cropSelectionScreenBounds, visibleCropSelectionForBounds } from "../src/ui/pages/CanvasWorkspace/canvas/cropViewport.ts";
|
||||
import { cropSelectionFromScreenDrag, cropSelectionScreenBounds, visibleCropSelectionForBounds } from "../src/ui/pages/CanvasWorkspace/canvas/cropViewport.ts";
|
||||
|
||||
const source = {
|
||||
id: "cad-source",
|
||||
@@ -74,3 +74,17 @@ test("keeps the full crop when the image already fits the safe viewport", () =>
|
||||
|
||||
assert.deepEqual(visibleCropSelectionForBounds(imageBounds, { width: 1200, height: 800 }), { x: 0, y: 0, width: 1, height: 1 });
|
||||
});
|
||||
|
||||
test("clamps a manually drawn crop to the currently visible image region", () => {
|
||||
const imageBounds = { left: -200, top: -100, width: 1000, height: 800 };
|
||||
const visibleSelection = { x: 0.2, y: 0.125, width: 0.6, height: 0.75 };
|
||||
|
||||
assert.deepEqual(
|
||||
cropSelectionFromScreenDrag(imageBounds, visibleSelection, { x: 0, y: 0 }, { x: 900, y: 700 }),
|
||||
visibleSelection
|
||||
);
|
||||
assert.deepEqual(
|
||||
cropSelectionFromScreenDrag(imageBounds, visibleSelection, { x: 100, y: 140 }, { x: 500, y: 460 }),
|
||||
{ x: 0.3, y: 0.3, width: 0.4, height: 0.4 }
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user