功能增加

This commit is contained in:
andy committed 2026-09-11 15:33:18 +08:00
1 parent b340fc7ad7
commit f1993eb388
69 files changed
+2243 -162

No files matched your search

+49
View File
@@ -0,0 +1,49 @@
import { describe, expect, it } from "vitest";
import { canvasAnnotationPoint, constrainCanvasView, fitCanvasImage, FIT_CANVAS_VIEW, zoomCanvasAt } from "@/lib/client/seedream-viewport";
import { buildSeedreamInteractivePrompt } from "@/lib/seedream/creation";
describe("Seedream canvas view geometry", () => {
const viewport = { width: 800, height: 500 };
it.each([{ width: 1000, height: 2000 }, { width: 2000, height: 1000 }])("fits a $width × $height image without stretching or inner scrollbars", (image) => {
const fitted = fitCanvasImage(image, viewport);
expect(fitted.width).toBeLessThanOrEqual(780);
expect(fitted.height).toBeLessThanOrEqual(480);
expect(fitted.width / fitted.height).toBeCloseTo(image.width / image.height);
});
it("keeps the cursor over the same image point during zoom", () => {
const fitted = fitCanvasImage({ width: 1000, height: 1000 }, viewport);
const before = { zoom: 2, x: 30, y: -20 };
const anchor = { x: 100, y: 80 };
const after = zoomCanvasAt(before, 3, anchor, fitted, viewport);
expect((anchor.x - after.x) / after.zoom).toBeCloseTo((anchor.x - before.x) / before.zoom);
expect((anchor.y - after.y) / after.zoom).toBeCloseTo((anchor.y - before.y) / before.zoom);
});
it("constrains pan at image edges and restores a centered fit", () => {
const fitted = { width: 240, height: 480 };
expect(constrainCanvasView({ zoom: 3, x: 900, y: -9999 }, fitted, viewport)).toEqual({ zoom: 3, x: 0, y: -470 });
expect(constrainCanvasView(FIT_CANVAS_VIEW, fitted, viewport)).toEqual(FIT_CANVAS_VIEW);
expect(constrainCanvasView({ zoom: 99, x: 0, y: 0 }, fitted, viewport).zoom).toBe(8);
expect(constrainCanvasView({ zoom: 0.01, x: 0, y: 0 }, fitted, viewport).zoom).toBe(0.25);
});
it("maps zoomed and panned box, point and brush coordinates back to the original image", () => {
const normalized = [{ x: 100, y: 200 }, { x: 456, y: 321 }, { x: 700, y: 800 }];
for (const bounds of [
{ left: 100, top: 50, width: 400, height: 600 },
{ left: -720, top: -380, width: 1600, height: 2400 },
{ left: 320, top: 120, width: 800, height: 1200 }
]) {
const points = normalized.map((point) => canvasAnnotationPoint({ x: bounds.left + bounds.width * point.x / 1000, y: bounds.top + bounds.height * point.y / 1000 }, bounds));
expect(points).toEqual(normalized);
expect(buildSeedreamInteractivePrompt("修改 @标注1", [{ id: "point", index: 1, kind: "point", point: points[1]! }])).toBe("修改 图1<point>456 321</point>");
}
});
it("clamps drawing outside the image and ignores an unloaded image", () => {
expect(canvasAnnotationPoint({ x: -1, y: 999 }, { left: 0, top: 0, width: 100, height: 100 })).toEqual({ x: 0, y: 1000 });
expect(canvasAnnotationPoint({ x: 0, y: 0 }, { left: 0, top: 0, width: 0, height: 0 })).toBeNull();
});
});