mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-30 01:27:26 +08:00
This commit is contained in:
1 parent
249dacb278
commit
1c20287807
6 files changed
+181
-35
No files matched your search
+14
-3
@@ -69,6 +69,11 @@
|
||||
</select>
|
||||
<span>对象</span>
|
||||
</div>
|
||||
<div class="editor-group">
|
||||
<div class="form-unit text-size"><input id="textSize" type="number" min="1" step="any" required aria-label="字号" disabled><span>pt</span></div>
|
||||
<input id="textColor" class="color-input" type="color" value="#000000" aria-label="文字颜色" title="文字颜色" disabled>
|
||||
<span>文字</span>
|
||||
</div>
|
||||
<div class="editor-group">
|
||||
<button id="insertTextButton" class="button" type="button" aria-label="添加文字">文字</button>
|
||||
<button id="insertImageButton" class="button" type="button" aria-label="添加图片">图片</button>
|
||||
@@ -152,9 +157,15 @@
|
||||
<button id="insertFontAdd" class="icon-button" type="button" title="添加字体" aria-label="添加字体">+</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="insertSizeRow" class="form-row">
|
||||
<label for="insertSize">字号</label>
|
||||
<div class="form-unit"><input id="insertSize" type="number" value="12" min="1" step="any" required><span>pt</span></div>
|
||||
<div class="form-pair">
|
||||
<div id="insertSizeRow" class="form-row">
|
||||
<label for="insertSize">字号</label>
|
||||
<div class="form-unit text-size"><input id="insertSize" type="number" value="12" min="1" step="any" required><span>pt</span></div>
|
||||
</div>
|
||||
<div id="insertColorRow" class="form-row">
|
||||
<label for="insertColor">颜色</label>
|
||||
<input id="insertColor" class="color-input" type="color" value="#000000">
|
||||
</div>
|
||||
</div>
|
||||
<div id="insertImageRow" class="form-row" hidden>
|
||||
<label for="insertImage">图片</label>
|
||||
|
||||
+32
-4
@@ -108,7 +108,8 @@ a:focus-visible {
|
||||
grid-template-columns: repeat(5, max-content);
|
||||
}
|
||||
|
||||
.editor-group:has(#insertTextButton) {
|
||||
.editor-group:has(#insertTextButton),
|
||||
.editor-group:has(#textSize) {
|
||||
grid-template-columns: repeat(2, max-content);
|
||||
}
|
||||
|
||||
@@ -120,8 +121,7 @@ a:focus-visible {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.editor-group > button,
|
||||
.editor-group > select {
|
||||
.editor-group > :not(span) {
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
@@ -419,7 +419,8 @@ button:not(:disabled):hover {
|
||||
.form-row input[type="text"],
|
||||
.form-row input[type="number"],
|
||||
.form-row input[type="file"],
|
||||
.form-row select {
|
||||
.form-row select,
|
||||
.text-size input {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
height: var(--control-height);
|
||||
@@ -430,6 +431,33 @@ button:not(:disabled):hover {
|
||||
color: #1f2428;
|
||||
}
|
||||
|
||||
.form-unit.text-size {
|
||||
grid-template-columns: calc(2em + 22px) auto;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.color-input {
|
||||
width: calc(2em + 22px);
|
||||
height: var(--control-height);
|
||||
padding: 3px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 0;
|
||||
background: #ffffff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.color-input::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.color-input::-webkit-color-swatch {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.color-input::-moz-color-swatch {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.form-row input[type="file"] {
|
||||
padding: 0;
|
||||
color: var(--text-muted);
|
||||
|
||||
+56
-7
@@ -89,6 +89,8 @@ const el = {
|
||||
editTextButton: document.querySelector("#editTextButton"),
|
||||
copyObjectButton: document.querySelector("#copyObjectButton"),
|
||||
objectOrder: document.querySelector("#objectOrder"),
|
||||
textSize: document.querySelector("#textSize"),
|
||||
textColor: document.querySelector("#textColor"),
|
||||
undoButton: document.querySelector("#undoButton"),
|
||||
redoButton: document.querySelector("#redoButton"),
|
||||
insertTextButton: document.querySelector("#insertTextButton"),
|
||||
@@ -120,11 +122,13 @@ const el = {
|
||||
insertTextRow: document.querySelector("#insertTextRow"),
|
||||
insertFontRow: document.querySelector("#insertFontRow"),
|
||||
insertSizeRow: document.querySelector("#insertSizeRow"),
|
||||
insertColorRow: document.querySelector("#insertColorRow"),
|
||||
insertImageRow: document.querySelector("#insertImageRow"),
|
||||
insertText: document.querySelector("#insertText"),
|
||||
insertFont: document.querySelector("#insertFont"),
|
||||
insertFontAdd: document.querySelector("#insertFontAdd"),
|
||||
insertSize: document.querySelector("#insertSize"),
|
||||
insertColor: document.querySelector("#insertColor"),
|
||||
insertImage: document.querySelector("#insertImage"),
|
||||
insertStatus: document.querySelector("#insertStatus"),
|
||||
insertCancel: document.querySelector("#insertCancel"),
|
||||
@@ -249,6 +253,17 @@ el.editTextButton.addEventListener("click", () => {
|
||||
openInsertPanel(true, canvasEditor.selected);
|
||||
}
|
||||
});
|
||||
el.textSize.addEventListener("change", () => changeTextStyle(false));
|
||||
el.textColor.addEventListener("change", () => changeTextStyle(true));
|
||||
el.textSize.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter" || event.key === "Escape") {
|
||||
event.preventDefault();
|
||||
if (event.key === "Escape") {
|
||||
updateObjectControls(canvasEditor.selected, true);
|
||||
}
|
||||
el.textSize.blur();
|
||||
}
|
||||
});
|
||||
el.copyObjectButton.addEventListener("click", () => {
|
||||
const item = canvasEditor.selected;
|
||||
if (!item) {
|
||||
@@ -628,11 +643,12 @@ async function openInsertPanel(text, item = null) {
|
||||
if (item) {
|
||||
state.insertFonts = [];
|
||||
el.insertText.value = item.text;
|
||||
el.insertSize.value = Number((item.size * 72 / 25.4).toPrecision(12));
|
||||
el.insertSize.value = textPoints(item.size);
|
||||
el.insertColor.value = item.color;
|
||||
}
|
||||
el.insertPanel.setAttribute("aria-label", item ? "修改文字" : text ? "添加文字" : "添加图片");
|
||||
el.insertSubmit.textContent = item ? "修改" : "添加";
|
||||
for (const [row, input] of [[el.insertTextRow, el.insertText], [el.insertFontRow, el.insertFont], [el.insertSizeRow, el.insertSize]]) {
|
||||
for (const [row, input] of [[el.insertTextRow, el.insertText], [el.insertFontRow, el.insertFont], [el.insertSizeRow, el.insertSize], [el.insertColorRow, el.insertColor]]) {
|
||||
row.hidden = !text;
|
||||
input.disabled = !text;
|
||||
}
|
||||
@@ -690,16 +706,20 @@ async function insertObject(event) {
|
||||
return;
|
||||
}
|
||||
const points = Number(el.insertSize.value);
|
||||
const size = item && points === Number((item.size * 72 / 25.4).toPrecision(12)) ? item.size : points * 25.4 / 72;
|
||||
const size = item && points === textPoints(item.size) ? item.size : points * 25.4 / 72;
|
||||
const doc = item
|
||||
? await callWASM("ofdgoUpdateText", item.index, item.id, el.insertText.value, data, size)
|
||||
: text ? await callWASM("ofdgoInsertText", index, el.insertText.value, data, x, y, size)
|
||||
? await callWASM("ofdgoUpdateText", item.index, item.id, el.insertText.value, data, size, el.insertColor.value === item.color ? null : el.insertColor.value)
|
||||
: text ? await callWASM("ofdgoInsertText", index, el.insertText.value, data, x, y, size, el.insertColor.value)
|
||||
: await callWASM("ofdgoInsertImage", index, data, x, y, page.width - x * 2);
|
||||
if (openSeq !== state.openSeq) {
|
||||
return;
|
||||
}
|
||||
setEditorInfo(doc);
|
||||
el.insertPanel.close();
|
||||
if (item && doc.revision === state.editorInfo?.revision) {
|
||||
el.viewerPanel.focus({ preventScroll: true });
|
||||
return;
|
||||
}
|
||||
setEditorInfo(doc);
|
||||
canvasEditor.selectLast = !item;
|
||||
state.selectObjects = true;
|
||||
setPan(false);
|
||||
@@ -723,6 +743,28 @@ async function insertObject(event) {
|
||||
}
|
||||
}
|
||||
|
||||
function textPoints(size) {
|
||||
return Number((size * 72 / 25.4).toPrecision(12));
|
||||
}
|
||||
|
||||
async function changeTextStyle(color) {
|
||||
const item = canvasEditor.selected;
|
||||
if (!item || item.image || !state.ready || state.exporting) {
|
||||
return;
|
||||
}
|
||||
if (!color && !el.textSize.checkValidity()) {
|
||||
showError(new Error("字号无效"), false);
|
||||
updateObjectControls(item, true);
|
||||
return;
|
||||
}
|
||||
const size = color || Number(el.textSize.value) === textPoints(item.size) ? item.size : Number(el.textSize.value) * 25.4 / 72;
|
||||
const fill = color && el.textColor.value !== item.color ? el.textColor.value : null;
|
||||
if (size !== item.size || fill !== null) {
|
||||
await changeDocument("ofdgoUpdateText", item, color ? null : item.text, null, size, fill);
|
||||
}
|
||||
updateObjectControls(canvasEditor.selected, true);
|
||||
}
|
||||
|
||||
async function changeDocument(name, item, ...args) {
|
||||
if (!state.editing || document.body.hasAttribute("aria-busy")) {
|
||||
return;
|
||||
@@ -3796,10 +3838,17 @@ function updateEditorTools() {
|
||||
el.redoButton.disabled = !state.editorInfo?.canRedo || !state.ready || state.exporting;
|
||||
}
|
||||
|
||||
function updateObjectControls(item) {
|
||||
function updateObjectControls(item, reset = false) {
|
||||
const disabled = !item || !state.ready || state.exporting;
|
||||
el.deleteObjectButton.disabled = el.copyObjectButton.disabled = disabled;
|
||||
el.editTextButton.disabled = !item || item.image || !state.ready || state.exporting;
|
||||
el.textSize.disabled = el.textColor.disabled = el.editTextButton.disabled;
|
||||
if (reset || el.textSize.disabled || document.activeElement !== el.textSize) {
|
||||
el.textSize.value = item && !item.image ? textPoints(item.size) : "";
|
||||
}
|
||||
if (reset || el.textColor.disabled || document.activeElement !== el.textColor) {
|
||||
el.textColor.value = item && !item.image ? item.color : "#000000";
|
||||
}
|
||||
el.objectOrder.disabled = disabled || item.count <= 1;
|
||||
for (const option of el.objectOrder.options) {
|
||||
option.disabled = disabled || (["up", "top"].includes(option.value) ? item.order === item.count - 1 : item.order === 0);
|
||||
|
||||
@@ -119,13 +119,14 @@ export class CanvasEditor {
|
||||
return;
|
||||
}
|
||||
const node = event.target.closest(".edit-object");
|
||||
if (!node) {
|
||||
this.select(null);
|
||||
if (node) {
|
||||
event.preventDefault();
|
||||
}
|
||||
this.viewer.focus({ preventScroll: true });
|
||||
this.select(node ? this.nodes.get(node) : null);
|
||||
if (!node || this.options.busy()) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
this.select(this.nodes.get(node));
|
||||
this.viewer.focus({ preventScroll: true });
|
||||
const item = this.selected;
|
||||
this.drag = {
|
||||
item, pointerID: event.pointerId, corner: event.target.dataset.corner || "",
|
||||
|
||||
Reference in new issue
Block a user