feat(编辑能力): 优化编辑工具栏布局与擦除操作
build.yaml / build (push) Successful in 39s

This commit is contained in:
xiaoqidun committed 2026-09-17 01:43:27 +08:00
1 parent 7bf9f7b3b7
commit 656adbecfe
3 files changed
+62 -60

No files matched your search

+17 -18
View File
@@ -91,11 +91,18 @@
</select>
<button id="objectStyleButton" class="editor-group-action" type="button" title="对象样式" aria-label="对象样式" aria-haspopup="dialog" aria-controls="objectStylePanel" disabled>对象</button>
</div>
<div class="editor-group editor-erase">
<button id="eraseObjectButton" class="button" type="button" title="整对象擦除" aria-label="整对象擦除" aria-pressed="false">对象</button>
<button id="eraseRegionButton" class="button" type="button" title="矩形擦除(视觉裁剪)" aria-label="矩形擦除" aria-pressed="false">矩形</button>
<button id="erasePathButton" class="button" type="button" title="套索擦除(视觉裁剪)" aria-label="套索擦除" aria-pressed="false">套索</button>
<span>擦除</span>
<div class="editor-group editor-transform">
<select id="objectRotate" class="order-select" aria-label="对象旋转" disabled>
<option value="" hidden>旋转</option>
<option value="90">右转90°</option>
<option value="-90">左转90°</option>
</select>
<select id="objectFlip" class="order-select" aria-label="对象翻转" disabled>
<option value="" hidden>翻转</option>
<option value="horizontal">水平</option>
<option value="vertical">垂直</option>
</select>
<button id="objectBoundsButton" class="editor-group-action" type="button" title="位置尺寸" aria-label="位置尺寸" aria-haspopup="dialog" aria-controls="objectBoundsPanel" disabled>变换</button>
</div>
<div class="editor-group">
<button id="insertTextButton" class="button" type="button" aria-label="添加文字" aria-pressed="false">文字</button>
@@ -109,7 +116,7 @@
<div class="editor-group">
<div class="text-font"><div class="font-picker"><input id="textFont" type="text" role="combobox" aria-label="字体" title="字体" aria-autocomplete="list" aria-controls="textFontList" aria-expanded="false" autocomplete="off" spellcheck="false" disabled><button id="textFontToggle" type="button" title="选择字体" aria-label="选择字体" tabindex="-1" disabled></button></div><button id="textFontAdd" class="icon-button" type="button" title="添加字体" aria-label="添加字体">+</button></div>
<div id="textFontList" class="font-listbox" role="listbox" aria-label="字体列表" popover="manual"></div>
<div class="editor-number"><input id="textSize" type="number" min="1" step="any" required aria-label="字号" disabled><span>pt</span></div>
<label class="editor-field"><span>字号</span><span class="editor-number"><input id="textSize" type="number" min="1" step="any" required aria-label="字号" disabled><span>pt</span></span></label>
<input id="textColor" class="color-input" type="color" value="#000000" aria-label="文字颜色" title="文字颜色" disabled>
<span>文字</span>
</div>
@@ -142,18 +149,10 @@
<button id="resetCropButton" class="button" type="button" aria-label="还原图片" disabled>还原</button>
<span>图片</span>
</div>
<div class="editor-group editor-transform">
<select id="objectRotate" class="order-select" aria-label="对象旋转" disabled>
<option value="" hidden>旋转</option>
<option value="90">右转90°</option>
<option value="-90">左转90°</option>
</select>
<select id="objectFlip" class="order-select" aria-label="对象翻转" disabled>
<option value="" hidden>翻转</option>
<option value="horizontal">水平</option>
<option value="vertical">垂直</option>
</select>
<button id="objectBoundsButton" class="editor-group-action" type="button" title="位置尺寸" aria-label="位置尺寸" aria-haspopup="dialog" aria-controls="objectBoundsPanel" disabled>变换</button>
<div class="editor-group editor-erase">
<button id="eraseButton" class="button" type="button" title="擦除" aria-label="擦除" aria-pressed="false">擦除</button>
<select id="eraseMode" aria-label="擦除方式" title="擦除方式,矩形和套索为视觉裁剪"><option value="erase-object">对象</option><option value="erase-region">矩形</option><option value="erase-path">套索</option></select>
<span>擦除</span>
</div>
<div class="editor-group">
<select id="addPageButton" aria-label="新增页面" title="新增页面"><option value="" hidden>新增</option><option value="blank">空白</option><option value="import">插页</option></select>
+26 -23
View File
@@ -89,7 +89,6 @@ a:focus-visible {
display: flex;
max-height: 40dvh;
overflow: auto;
gap: 8px;
padding: 8px 10px 6px;
border-bottom: 1px solid var(--line);
background: var(--panel);
@@ -102,35 +101,32 @@ a:focus-visible {
.editor-group {
display: grid;
flex: 0 0 auto;
flex: 1 0 auto;
justify-content: center;
grid-template-columns: repeat(3, max-content);
grid-template-rows: repeat(2, 28px) 16px;
column-gap: 4px;
row-gap: 4px;
padding-right: 8px;
padding: 0 8px;
border-right: 1px solid var(--line);
}
.editor-file,
.editor-erase,
.editor-image {
grid-template-columns: repeat(2, max-content);
}
.editor-transform {
.editor-transform,
.editor-erase {
grid-template-columns: max-content;
}
#eraseObjectButton {
grid-row: span 2;
height: 100%;
}
.editor-image > select {
grid-column: 1 / -1;
}
.editor-paragraph > .editor-field {
.editor-paragraph > .editor-field,
.editor-group:has(#textFont) > .editor-field {
grid-column: auto;
}
@@ -142,7 +138,8 @@ a:focus-visible {
display: grid;
align-items: center;
grid-column: 1 / -1;
grid-template-columns: 2em minmax(0, 1fr);
grid-template-columns: 2em 86px;
justify-content: space-between;
gap: 6px;
white-space: nowrap;
}
@@ -189,17 +186,15 @@ a:focus-visible {
}
.editor-group:has(#textFont) {
grid-template-columns: 102px 54px;
grid-template-columns: 160px 32px;
}
.editor-paragraph {
width: 194px;
grid-template-columns: 54px minmax(0, 1fr);
grid-template-columns: 54px max-content;
}
.editor-group:has(#shapeFill) {
width: 180px;
grid-template-columns: repeat(2, minmax(0, 1fr));
grid-template-columns: repeat(2, 84px);
}
.editor-file #saveButton {
@@ -211,11 +206,6 @@ a:focus-visible {
grid-column: 2;
}
#textFont {
width: 100%;
min-width: 0;
}
.font-picker {
display: flex;
min-width: 0;
@@ -227,6 +217,7 @@ a:focus-visible {
.font-picker #textFont {
flex: 1 1 0;
width: 0;
min-width: 0;
text-overflow: ellipsis;
padding: 0 6px;
border: 0;
@@ -333,7 +324,15 @@ a:focus-visible {
accent-color: var(--accent);
}
.editor-group:first-child {
flex-grow: 0.5;
justify-content: start;
padding-left: 0;
}
.editor-group:last-child {
flex-grow: 0.5;
justify-content: end;
padding-right: 0;
border-right: 0;
}
@@ -766,12 +765,16 @@ button:not(:disabled):hover {
.text-font {
display: grid;
width: 160px;
width: 196px;
grid-template-columns: minmax(0, 1fr) auto;
grid-column: 1 / -1;
gap: 4px;
}
.text-font .icon-button {
width: 32px;
}
.form-row input[aria-invalid="true"] {
border-color: #b14343;
}
+19 -19
View File
@@ -152,9 +152,8 @@ const el = {
arrowTool: document.querySelector("#arrowTool"),
drawRectangleButton: document.querySelector("#drawRectangleButton"),
drawEllipseButton: document.querySelector("#drawEllipseButton"),
eraseObjectButton: document.querySelector("#eraseObjectButton"),
eraseRegionButton: document.querySelector("#eraseRegionButton"),
erasePathButton: document.querySelector("#erasePathButton"),
eraseButton: document.querySelector("#eraseButton"),
eraseMode: document.querySelector("#eraseMode"),
shapeFill: document.querySelector("#shapeFill"),
shapeFillColor: document.querySelector("#shapeFillColor"),
shapeStroke: document.querySelector("#shapeStroke"),
@@ -547,19 +546,13 @@ el.resetCropButton.addEventListener("click", () => {
});
editorClick(el.undoButton, () => changeDocument("ofdgoUndo"));
editorClick(el.redoButton, () => changeDocument("ofdgoRedo"));
for (const [button, tool] of [[el.drawLineButton, "line"], [el.drawRectangleButton, "rectangle"], [el.drawEllipseButton, "ellipse"],
[el.eraseObjectButton, "erase-object"], [el.eraseRegionButton, "erase-region"], [el.erasePathButton, "erase-path"]]) {
editorClick(button, () => {
if (!state.editing || document.body.hasAttribute("aria-busy")) {
return;
}
const next = canvasEditor.tool === tool ? "" : tool;
state.selectObjects = true;
setPan(false);
canvasEditor.setTool(next);
el.viewerPanel.focus({ preventScroll: true });
});
for (const [button, tool] of [[el.drawLineButton, "line"], [el.drawRectangleButton, "rectangle"], [el.drawEllipseButton, "ellipse"]]) {
editorClick(button, () => toggleDrawingTool(tool));
}
editorClick(el.eraseButton, () => toggleDrawingTool(el.eraseMode.value));
el.eraseMode.addEventListener("change", () => {
if (canvasEditor.tool.startsWith("erase-")) canvasEditor.setTool(el.eraseMode.value);
});
for (const input of [el.shapeFill, el.shapeFillColor, el.shapeStroke, el.shapeStrokeColor, el.shapeWidth]) {
input.addEventListener("change", changeShapeStyle);
}
@@ -1647,6 +1640,15 @@ async function changeShapeStyle() {
updateDrawingControls();
}
function toggleDrawingTool(tool) {
if (!state.editing || document.body.hasAttribute("aria-busy")) return;
const next = canvasEditor.tool === tool ? "" : tool;
state.selectObjects = true;
setPan(false);
canvasEditor.setTool(next);
el.viewerPanel.focus({ preventScroll: true });
}
function updateDrawingControls() {
const tool = canvasEditor.tool;
el.insertTextButton.setAttribute("aria-pressed", String(tool === "text"));
@@ -1661,10 +1663,8 @@ function updateDrawingControls() {
button.disabled = disabled || !pageCan("insert");
button.setAttribute("aria-pressed", String(tool === name));
}
for (const [button, name] of [[el.eraseObjectButton, "erase-object"], [el.eraseRegionButton, "erase-region"], [el.erasePathButton, "erase-path"]]) {
button.disabled = disabled;
button.setAttribute("aria-pressed", String(tool === name));
}
el.eraseButton.disabled = el.eraseMode.disabled = disabled;
el.eraseButton.setAttribute("aria-pressed", String(tool.startsWith("erase-")));
el.selectObjectButton.setAttribute("aria-pressed", String(canvasEditor.enabled && !tool));
const styleDisabled = disabled || (canvasEditor.selected?.type === "PathObject"
? !canEditObject(canvasEditor.selected, "update") : !pageCan("insert"));