mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 17:27:08 +08:00
feat(编辑能力): 支持组合内容直接编辑
This commit is contained in:
1 parent
9ee47731c9
commit
6dae7bdc20
7 files changed
+698
-242
No files matched your search
+26
-10
@@ -563,7 +563,7 @@ export class CanvasEditor {
|
||||
if (!event.altKey && this.enabled && item && !item.items && !this.input && !this.options.busy()
|
||||
&& target && (!target.dataset.corner || item.type === "TextObject")
|
||||
&& this.targetAt({ target, clientX: event.clientX, clientY: event.clientY }) === item) {
|
||||
this.options.onEdit(item);
|
||||
this.options.onEdit(item, canEditObject(item, "children") ? pagePoint(event.clientX, event.clientY, item.surface.getBoundingClientRect(), item.page, this.options.rotation()) : null);
|
||||
}
|
||||
});
|
||||
viewer.addEventListener("scroll", () => this.scroll());
|
||||
@@ -607,14 +607,15 @@ export class CanvasEditor {
|
||||
const layer = document.createElement("div");
|
||||
layer.className = "edit-layer";
|
||||
const artwork = new Map([...surface.querySelectorAll("[data-ofd-object], [data-ofd-child]")].map((node, order) => [node.getAttribute("data-ofd-object") || node.getAttribute("data-ofd-child"), { node, order }]));
|
||||
const objects = [...page.objects].sort((a, b) => (artwork.get(a.id)?.order ?? 0) - (artwork.get(b.id)?.order ?? 0));
|
||||
for (const object of objects) {
|
||||
const paintOrder = object => artwork.get(object.id)?.order ?? artwork.get(object.id.split("/")[0])?.order ?? 0;
|
||||
const objects = [...page.objects].sort((a, b) => paintOrder(a) - paintOrder(b));
|
||||
for (const [order, object] of objects.entries()) {
|
||||
const node = document.createElement("div");
|
||||
node.className = "edit-object";
|
||||
node.classList.toggle("read-only", !canEditObject(object, "move"));
|
||||
node.title = objectEditReason(object);
|
||||
node.tabIndex = 0;
|
||||
const item = { ...object, index, page: { width: page.width, height: page.height }, node, surface };
|
||||
const item = { ...object, order, index, page: { width: page.width, height: page.height }, node, surface };
|
||||
item.artwork = artwork.get(object.id)?.node;
|
||||
if (object.note) {
|
||||
const icon = document.createElement("span");
|
||||
@@ -760,6 +761,7 @@ export class CanvasEditor {
|
||||
}
|
||||
|
||||
setSelection(items) {
|
||||
items = items.filter(item => !items.some(parent => parent !== item && item.id.startsWith(parent.id + "/")));
|
||||
this.cancelNudge();
|
||||
const previous = this.selected;
|
||||
if (this.crop && (items.length !== 1 || items[0] !== this.crop.item)) this.closeCrop();
|
||||
@@ -805,6 +807,10 @@ export class CanvasEditor {
|
||||
item.node.classList.toggle("multi-selected", items.length > 1);
|
||||
item.node.setAttribute("data-pressed", "true");
|
||||
}
|
||||
for (const node of this.viewer.querySelectorAll(".edit-parent")) node.classList.remove("edit-parent");
|
||||
for (const item of items) {
|
||||
if (item.parent) this.pageItems(item.index).find(parent => parent.id === item.parent)?.node.classList.add("edit-parent");
|
||||
}
|
||||
this.options.onSelect(this.selected, previous);
|
||||
}
|
||||
|
||||
@@ -817,6 +823,16 @@ export class CanvasEditor {
|
||||
this.setSelection(items.includes(item) ? items.filter(member => member !== item) : [...items, item]);
|
||||
}
|
||||
|
||||
selectParent() {
|
||||
const item = this.selected;
|
||||
if (!item?.parent) return false;
|
||||
const parent = this.pageItems(item.index).find(parent => parent.id === item.parent);
|
||||
if (!parent) return false;
|
||||
this.select(parent);
|
||||
this.focus();
|
||||
return true;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.closeText();
|
||||
this.closeCrop();
|
||||
@@ -902,7 +918,7 @@ export class CanvasEditor {
|
||||
if (!this.drag.corner) {
|
||||
const selected = this.items();
|
||||
this.drag.targets = [...item.surface.querySelectorAll(".edit-object")]
|
||||
.map(node => this.nodes.get(node)).filter(member => !selected.includes(member));
|
||||
.map(node => this.nodes.get(node)).filter(member => !selected.some(item => item === member || item.id.startsWith(member.id + "/") || member.id.startsWith(item.id + "/")));
|
||||
this.drag.targets.push({ x: 0, y: 0, ...item.page });
|
||||
}
|
||||
if (lineShape(item.shape) && this.drag.corner) {
|
||||
@@ -930,7 +946,7 @@ export class CanvasEditor {
|
||||
event = { target, clientX: event.clientX, clientY: event.clientY };
|
||||
}
|
||||
const direct = this.nodes.get(event.target.closest(".edit-object, .edit-selection"));
|
||||
return event.target.dataset.corner || direct && !direct.contours ? direct : this.itemsAt(event)[0];
|
||||
return event.target.dataset.corner || direct && !direct.contours && (!direct.parent || this.items().some(selected => selected.id.startsWith(direct.parent + "/"))) ? direct : this.itemsAt(event)[0];
|
||||
}
|
||||
|
||||
itemsAt(event) {
|
||||
@@ -940,7 +956,7 @@ export class CanvasEditor {
|
||||
const rect = surface.getBoundingClientRect(), rotation = this.options.rotation();
|
||||
const point = pagePoint(event.clientX, event.clientY, rect, page, rotation);
|
||||
const tolerance = 3 * page.width / (rotation % 180 ? rect.height : rect.width);
|
||||
return [...surface.querySelectorAll(".edit-object")].map(node => this.nodes.get(node)).reverse().filter(item => item.type === "TextObject"
|
||||
return [...surface.querySelectorAll(".edit-object")].map(node => this.nodes.get(node)).reverse().filter(item => !item.parent || this.items().some(selected => selected.id.startsWith(item.parent + "/"))).filter(item => item.type === "TextObject"
|
||||
? point.x >= item.x - tolerance && point.x <= item.x + item.width + tolerance
|
||||
&& point.y >= item.y - tolerance && point.y <= item.y + item.height + tolerance
|
||||
: this.contains(item, point, tolerance));
|
||||
@@ -1256,7 +1272,7 @@ export class CanvasEditor {
|
||||
if (!page) return;
|
||||
event.preventDefault();
|
||||
this.focus();
|
||||
this.drag = { erase: this.tool, page, surface, items: [...surface.querySelectorAll(".edit-object")].map(node => this.nodes.get(node)),
|
||||
this.drag = { erase: this.tool, page, surface, items: [...surface.querySelectorAll(".edit-object")].map(node => this.nodes.get(node)).filter(item => !item.parent),
|
||||
erased: new Set(), shape: "rectangle", pointerID: event.pointerId, clientX: event.clientX, clientY: event.clientY,
|
||||
rect: surface.getBoundingClientRect(), rotation: this.options.rotation() };
|
||||
if (this.tool === "erase-region") Object.assign(this.drag, this.createPreview(surface, page, "rectangle",
|
||||
@@ -1315,7 +1331,7 @@ export class CanvasEditor {
|
||||
const items = [...drag.base];
|
||||
for (const node of drag.surface.querySelectorAll(".edit-object")) {
|
||||
const item = this.nodes.get(node);
|
||||
if (!items.includes(item) && item.x >= box.x && item.x+item.width <= box.x+box.width && item.y >= box.y && item.y+item.height <= box.y+box.height) {
|
||||
if (!item.parent && !items.includes(item) && item.x >= box.x && item.x+item.width <= box.x+box.width && item.y >= box.y && item.y+item.height <= box.y+box.height) {
|
||||
items.push(item);
|
||||
}
|
||||
}
|
||||
@@ -1458,7 +1474,7 @@ export class CanvasEditor {
|
||||
this.setTool("");
|
||||
return;
|
||||
}
|
||||
if (event.key === "Escape" && !this.input && this.enabled && !this.options.busy() && !this.nudge && this.options.onExitScope?.()) {
|
||||
if (event.key === "Escape" && !this.input && this.enabled && !this.options.busy() && !this.nudge && this.selectParent()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return;
|
||||
|
||||
Reference in new issue
Block a user