d424b56076
- Implemented CanvasPathEditor component for editing paths on the canvas. - Created editablePath module to handle path data manipulation and conversion to SVG. - Introduced pathPen module for managing path drawing with a pen tool, including anchor management and path data generation. - Added tests for editablePath and pathPen functionalities to ensure correctness of path editing and drawing behavior.
84 lines
2.9 KiB
JavaScript
84 lines
2.9 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import {
|
|
deletePathSegment,
|
|
getClosestSegmentLocation,
|
|
splitPathSegment
|
|
} from "leafer-x-path-editor";
|
|
|
|
test("splits an existing straight segment at the clicked position", () => {
|
|
const points = [{ x: 0, y: 0, move: true }, { x: 10, y: 0 }];
|
|
const segment = { fromIndex: 0, toIndex: 1, insertIndex: 1 };
|
|
|
|
const result = splitPathSegment(points, segment, 0.4);
|
|
|
|
assert.deepEqual(result, [{ x: 0, y: 0, move: true }, { x: 4, y: 0 }, { x: 10, y: 0 }]);
|
|
});
|
|
|
|
test("keeps a closed path closed when its closing segment is split", () => {
|
|
const result = splitPathSegment(
|
|
[{ x: 0, y: 0, move: true }, { x: 10, y: 0, closed: true }],
|
|
{ fromIndex: 1, toIndex: 0, insertIndex: 2, closing: true },
|
|
0.5
|
|
);
|
|
|
|
assert.deepEqual(result, [
|
|
{ x: 0, y: 0, move: true },
|
|
{ x: 10, y: 0, closed: false },
|
|
{ x: 5, y: 0, closed: true }
|
|
]);
|
|
});
|
|
|
|
test("splits quadratic and cubic segments without changing their geometry", () => {
|
|
const quadratic = splitPathSegment(
|
|
[{ x: 0, y: 0, move: true, x2: 0, y2: 10 }, { x: 10, y: 0 }],
|
|
{ fromIndex: 0, toIndex: 1, insertIndex: 1 },
|
|
0.5
|
|
);
|
|
assert.deepEqual(quadratic, [
|
|
{ x: 0, y: 0, move: true, x2: undefined, y2: undefined },
|
|
{ x: 2.5, y: 5, x1: 0, y1: 5, x2: 5, y2: 5, mode: "no-mirror" },
|
|
{ x: 10, y: 0, x1: undefined, y1: undefined }
|
|
]);
|
|
|
|
const cubic = splitPathSegment(
|
|
[{ x: 0, y: 0, move: true, x2: 0, y2: 10 }, { x: 10, y: 0, x1: 10, y1: 10 }],
|
|
{ fromIndex: 0, toIndex: 1, insertIndex: 1 },
|
|
0.5
|
|
);
|
|
assert.deepEqual(cubic, [
|
|
{ x: 0, y: 0, move: true, x2: 0, y2: 5 },
|
|
{ x: 5, y: 7.5, x1: 2.5, y1: 7.5, x2: 7.5, y2: 7.5, mode: "no-mirror" },
|
|
{ x: 10, y: 0, x1: 10, y1: 5 }
|
|
]);
|
|
});
|
|
|
|
test("finds the insertion point nearest to the pointer", () => {
|
|
const points = [{ x: 0, y: 0, move: true }, { x: 10, y: 0 }];
|
|
const location = getClosestSegmentLocation(points, { fromIndex: 0, toIndex: 1, insertIndex: 1 }, { x: 3, y: 5 });
|
|
|
|
assert.ok(Math.abs(location.t - 0.3) < 0.0001);
|
|
assert.deepEqual(location.point, { x: 3, y: 0 });
|
|
});
|
|
|
|
test("deletes the selected segment without reconnecting its endpoints", () => {
|
|
const openResult = deletePathSegment(
|
|
[{ x: 0, y: 0, move: true, x2: 4, y2: 0 }, { x: 10, y: 0, x1: 6, y1: 0 }],
|
|
{ fromIndex: 0, toIndex: 1, insertIndex: 1 }
|
|
);
|
|
assert.deepEqual(openResult, [
|
|
{ x: 0, y: 0, move: true, x2: undefined, y2: undefined },
|
|
{ x: 10, y: 0, x1: undefined, y1: undefined, move: true, type: "start" }
|
|
]);
|
|
|
|
const closedResult = deletePathSegment(
|
|
[{ x: 0, y: 0, move: true, x1: 2, y1: 2 }, { x: 10, y: 0, x2: 8, y2: 2, closed: true }],
|
|
{ fromIndex: 1, toIndex: 0, insertIndex: 2, closing: true }
|
|
);
|
|
assert.deepEqual(closedResult, [
|
|
{ x: 0, y: 0, move: true, x1: undefined, y1: undefined },
|
|
{ x: 10, y: 0, x2: undefined, y2: undefined, closed: false }
|
|
]);
|
|
});
|